1 // Copyright (C) 2004, 2005 Arkadiy Vertleyb
2 // Copyright (C) 2005 Peder Holt
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #ifndef BOOST_TYPEOF_TYPEOF_IMPL_HPP_INCLUDED
7 #define BOOST_TYPEOF_TYPEOF_IMPL_HPP_INCLUDED
8 
9 #include <boost/preprocessor/repetition/enum.hpp>
10 #include <boost/typeof/constant.hpp>
11 #include <boost/typeof/encode_decode.hpp>
12 #include <boost/typeof/vector.hpp>
13 #include <boost/type_traits/enable_if.hpp>
14 #include <boost/type_traits/is_function.hpp>
15 #include <cstddef> // for std::size_t
16 
17 #define BOOST_TYPEOF_VECTOR(n) BOOST_PP_CAT(boost::type_of::vector, n)
18 
19 #define BOOST_TYPEOF_sizer_item(z, n, _)\
20     char item ## n[V::item ## n ::value];
21 
22 namespace boost { namespace type_of {
23     template<class V>
24     struct sizer
25     {
26         // char item0[V::item0::value];
27         // char item1[V::item1::value];
28         // ...
29 
30         BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE, BOOST_TYPEOF_sizer_item, ~)
31     };
32 }}
33 
34 #undef BOOST_TYPEOF_sizer_item
35 
36 //
37 namespace boost { namespace type_of {
38 # ifdef BOOST_NO_SFINAE
39     template<class V, class T>
40     sizer<typename encode_type<V, T>::type> encode(const T&);
41 # else
42     template<class V, class T>
43     typename enable_if_<
44         is_function<T>::value,
45         sizer<typename encode_type<V, T>::type> >::type encode(T&);
46 
47     template<class V, class T>
48     typename enable_if_<
49         !is_function<T>::value,
50         sizer<typename encode_type<V, T>::type> >::type encode(const T&);
51 # endif
52 }}
53 //
54 namespace boost { namespace type_of {
55 
56     template<class V>
57     struct decode_begin
58     {
59         typedef typename decode_type<typename V::begin>::type type;
60     };
61 }}
62 
63 #define BOOST_TYPEOF_TYPEITEM(z, n, expr)\
64     boost::type_of::constant<std::size_t,sizeof(boost::type_of::encode<BOOST_TYPEOF_VECTOR(0)<> >(expr).item ## n)>
65 
66 #define BOOST_TYPEOF_ENCODED_VECTOR(Expr)                                   \
67     BOOST_TYPEOF_VECTOR(BOOST_TYPEOF_LIMIT_SIZE)<                           \
68         BOOST_PP_ENUM(BOOST_TYPEOF_LIMIT_SIZE, BOOST_TYPEOF_TYPEITEM, Expr) \
69     >
70 
71 #define BOOST_TYPEOF(Expr)\
72     boost::type_of::decode_begin<BOOST_TYPEOF_ENCODED_VECTOR(Expr) >::type
73 
74 #define BOOST_TYPEOF_TPL typename BOOST_TYPEOF
75 
76 //offset_vector is used to delay the insertion of data into the vector in order to allow
77 //encoding to be done in many steps
78 namespace boost { namespace type_of {
79     template<typename V,typename Offset>
80     struct offset_vector {
81     };
82 
83     template<class V,class Offset,class T>
84     struct push_back<boost::type_of::offset_vector<V,Offset>,T> {
85         typedef offset_vector<V,typename Offset::prior> type;
86     };
87 
88     template<class V,class T>
89     struct push_back<boost::type_of::offset_vector<V,constant<std::size_t,0> >,T> {
90         typedef typename push_back<V,T>::type type;
91     };
92 }}
93 
94 #define BOOST_TYPEOF_NESTED_TYPEITEM(z, n, expr)\
95     BOOST_STATIC_CONSTANT(int,BOOST_PP_CAT(value,n) = sizeof(boost::type_of::encode<_typeof_start_vector>(expr).item ## n));\
96     typedef boost::type_of::constant<std::size_t,BOOST_PP_CAT(self_t::value,n)> BOOST_PP_CAT(item,n);
97 
98 #ifdef __DMC__
99 #define BOOST_TYPEOF_NESTED_TYPEITEM_2(z,n,expr)\
100     typedef typename _typeof_encode_fraction<iteration>::BOOST_PP_CAT(item,n) BOOST_PP_CAT(item,n);
101 
102 #define BOOST_TYPEOF_FRACTIONTYPE()\
103     BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE,BOOST_TYPEOF_NESTED_TYPEITEM_2,_)\
104     typedef _typeof_fraction_iter<Pos> fraction_type;
105 #else
106 #define BOOST_TYPEOF_FRACTIONTYPE()\
107     typedef _typeof_encode_fraction<self_t::iteration> fraction_type;
108 #endif
109 
110 #ifdef BOOST_BORLANDC
111 namespace boost { namespace type_of {
112     template<typename Pos,typename Iter>
113     struct generic_typeof_fraction_iter {
114         typedef generic_typeof_fraction_iter<Pos,Iter> self_t;
115         static const int pos=(Pos::value);
116         static const int iteration=(pos/5);
117         static const int where=pos%5;
118         typedef typename Iter::template _apply_next<self_t::iteration>::type fraction_type;
119         typedef generic_typeof_fraction_iter<typename Pos::next,Iter> next;
120         typedef typename v_iter<fraction_type,constant<int, self_t::where> >::type type;
121     };
122 }}
123 #define BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr) \
124         template<int _Typeof_Iteration>\
125         struct _typeof_encode_fraction {\
126             typedef _typeof_encode_fraction<_Typeof_Iteration> self_t;\
127             BOOST_STATIC_CONSTANT(int,_typeof_encode_offset = (_Typeof_Iteration*BOOST_TYPEOF_LIMIT_SIZE));\
128             typedef boost::type_of::offset_vector<BOOST_TYPEOF_VECTOR(0)<>,boost::type_of::constant<std::size_t,self_t::_typeof_encode_offset> > _typeof_start_vector;\
129             BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE,BOOST_TYPEOF_NESTED_TYPEITEM,expr)\
130             template<int Next>\
131             struct _apply_next {\
132                 typedef _typeof_encode_fraction<Next> type;\
133             };\
134         };\
135         template<typename Pos>\
136         struct _typeof_fraction_iter {\
137             typedef boost::type_of::generic_typeof_fraction_iter<Pos,_typeof_encode_fraction<0> > self_t;\
138             typedef typename self_t::next next;\
139             typedef typename self_t::type type;\
140         };
141 #else
142 #define BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr) \
143         template<int _Typeof_Iteration>\
144         struct _typeof_encode_fraction {\
145             typedef _typeof_encode_fraction<_Typeof_Iteration> self_t;\
146             BOOST_STATIC_CONSTANT(int,_typeof_encode_offset = (_Typeof_Iteration*BOOST_TYPEOF_LIMIT_SIZE));\
147             typedef boost::type_of::offset_vector<BOOST_TYPEOF_VECTOR(0)<>,boost::type_of::constant<std::size_t,self_t::_typeof_encode_offset> > _typeof_start_vector;\
148             BOOST_PP_REPEAT(BOOST_TYPEOF_LIMIT_SIZE,BOOST_TYPEOF_NESTED_TYPEITEM,expr)\
149         };\
150         template<typename Pos>\
151         struct _typeof_fraction_iter {\
152             typedef _typeof_fraction_iter<Pos> self_t;\
153             BOOST_STATIC_CONSTANT(int,pos=(Pos::value));\
154             BOOST_STATIC_CONSTANT(int,iteration=(pos/BOOST_TYPEOF_LIMIT_SIZE));\
155             BOOST_STATIC_CONSTANT(int,where=pos%BOOST_TYPEOF_LIMIT_SIZE);\
156             BOOST_TYPEOF_FRACTIONTYPE()\
157             typedef typename boost::type_of::v_iter<fraction_type,boost::type_of::constant<int,self_t::where> >::type type;\
158             typedef _typeof_fraction_iter<typename Pos::next> next;\
159         };
160 #endif
161 #ifdef __MWERKS__
162 
163 # define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
164 template<typename T>\
165 struct BOOST_PP_CAT(_typeof_template_,name) {\
166     BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr)\
167     typedef typename boost::type_of::decode_type<_typeof_fraction_iter<boost::type_of::constant<std::size_t,0> > >::type type;\
168 };\
169 typedef BOOST_PP_CAT(_typeof_template_,name)<int> name;
170 
171 # define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) BOOST_TYPEOF_NESTED_TYPEDEF(name,expr)
172 
173 #else
174 # define BOOST_TYPEOF_NESTED_TYPEDEF_TPL(name,expr) \
175     struct name {\
176         BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr)\
177         typedef typename boost::type_of::decode_type<_typeof_fraction_iter<boost::type_of::constant<std::size_t,0> > >::type type;\
178     };
179 
180 # define BOOST_TYPEOF_NESTED_TYPEDEF(name,expr) \
181     struct name {\
182         BOOST_TYPEOF_NESTED_TYPEDEF_IMPL(expr)\
183         typedef boost::type_of::decode_type<_typeof_fraction_iter<boost::type_of::constant<std::size_t,0> > >::type type;\
184     };
185 #endif
186 
187 #endif//BOOST_TYPEOF_COMPLIANT_TYPEOF_IMPL_HPP_INCLUDED
188