|
1 // Copyright (C) 2004 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_TEMPLATE_ENCODING_HPP_INCLUDED |
|
7 #define BOOST_TYPEOF_TEMPLATE_ENCODING_HPP_INCLUDED |
|
8 |
|
9 #include <boost/preprocessor/cat.hpp> |
|
10 #include <boost/preprocessor/repetition/enum_trailing.hpp> |
|
11 #include <boost/preprocessor/control/iif.hpp> |
|
12 #include <boost/preprocessor/detail/is_unary.hpp> |
|
13 #include <boost/preprocessor/repetition/repeat.hpp> |
|
14 #include <boost/preprocessor/tuple/eat.hpp> |
|
15 #include <boost/preprocessor/seq/transform.hpp> |
|
16 #include <boost/preprocessor/seq/for_each_i.hpp> |
|
17 #include <boost/preprocessor/seq/cat.hpp> |
|
18 |
|
19 #include <boost/typeof/encode_decode.hpp> |
|
20 #include <boost/typeof/int_encoding.hpp> |
|
21 |
|
22 #include <boost/typeof/type_template_param.hpp> |
|
23 #include <boost/typeof/integral_template_param.hpp> |
|
24 #include <boost/typeof/template_template_param.hpp> |
|
25 |
|
26 // The template parameter description, entered by the user, |
|
27 // is converted into a polymorphic "object" |
|
28 // that is used to generate the code responsible for |
|
29 // encoding/decoding the parameter, etc. |
|
30 |
|
31 // make sure to cat the sequence first, and only then add the prefix. |
|
32 #define BOOST_TYPEOF_MAKE_OBJ(elem) BOOST_PP_CAT(\ |
|
33 BOOST_TYPEOF_MAKE_OBJ,\ |
|
34 BOOST_PP_SEQ_CAT((_) BOOST_TYPEOF_TO_SEQ(elem))\ |
|
35 ) |
|
36 |
|
37 #define BOOST_TYPEOF_TO_SEQ(tokens) BOOST_TYPEOF_ ## tokens ## _BOOST_TYPEOF |
|
38 |
|
39 // BOOST_TYPEOF_REGISTER_TEMPLATE |
|
40 |
|
41 #define BOOST_TYPEOF_REGISTER_TEMPLATE_EXPLICIT_ID(Name, Params, Id)\ |
|
42 BOOST_TYPEOF_REGISTER_TEMPLATE_IMPL(\ |
|
43 Name,\ |
|
44 BOOST_TYPEOF_MAKE_OBJS(BOOST_TYPEOF_TOSEQ(Params)),\ |
|
45 BOOST_PP_SEQ_SIZE(BOOST_TYPEOF_TOSEQ(Params)),\ |
|
46 Id) |
|
47 |
|
48 #define BOOST_TYPEOF_REGISTER_TEMPLATE(Name, Params)\ |
|
49 BOOST_TYPEOF_REGISTER_TEMPLATE_EXPLICIT_ID(Name, Params, BOOST_TYPEOF_UNIQUE_ID()) |
|
50 |
|
51 #define BOOST_TYPEOF_OBJECT_MAKER(s, data, elem)\ |
|
52 BOOST_TYPEOF_MAKE_OBJ(elem) |
|
53 |
|
54 #define BOOST_TYPEOF_MAKE_OBJS(Params)\ |
|
55 BOOST_PP_SEQ_TRANSFORM(BOOST_TYPEOF_OBJECT_MAKER, ~, Params) |
|
56 |
|
57 // As suggested by Paul Mensonides: |
|
58 |
|
59 #define BOOST_TYPEOF_TOSEQ(x)\ |
|
60 BOOST_PP_IIF(\ |
|
61 BOOST_PP_IS_UNARY(x),\ |
|
62 x BOOST_PP_TUPLE_EAT(3), BOOST_PP_REPEAT\ |
|
63 )(x, BOOST_TYPEOF_TOSEQ_2, ~) |
|
64 |
|
65 #define BOOST_TYPEOF_TOSEQ_2(z, n, _) (class) |
|
66 |
|
67 // BOOST_TYPEOF_VIRTUAL |
|
68 |
|
69 #define BOOST_TYPEOF_CAT_4(a, b, c, d) BOOST_TYPEOF_CAT_4_I(a, b, c, d) |
|
70 #define BOOST_TYPEOF_CAT_4_I(a, b, c, d) a ## b ## c ## d |
|
71 |
|
72 #define BOOST_TYPEOF_VIRTUAL(Fun, Obj)\ |
|
73 BOOST_TYPEOF_CAT_4(BOOST_TYPEOF_, BOOST_PP_SEQ_HEAD(Obj), _, Fun) |
|
74 |
|
75 // BOOST_TYPEOF_SEQ_ENUM[_TRAILING][_1] |
|
76 // Two versions provided due to reentrancy issue |
|
77 |
|
78 #define BOOST_TYPEOF_SEQ_EXPAND_ELEMENT(z,n,seq)\ |
|
79 BOOST_PP_SEQ_ELEM(0,seq) (z,n,BOOST_PP_SEQ_ELEM(n,BOOST_PP_SEQ_ELEM(1,seq))) |
|
80 |
|
81 #define BOOST_TYPEOF_SEQ_ENUM(seq,macro)\ |
|
82 BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(seq),BOOST_TYPEOF_SEQ_EXPAND_ELEMENT,(macro)(seq)) |
|
83 |
|
84 #define BOOST_TYPEOF_SEQ_ENUM_TRAILING(seq,macro)\ |
|
85 BOOST_PP_ENUM_TRAILING(BOOST_PP_SEQ_SIZE(seq),BOOST_TYPEOF_SEQ_EXPAND_ELEMENT,(macro)(seq)) |
|
86 |
|
87 #define BOOST_TYPEOF_SEQ_EXPAND_ELEMENT_1(z,n,seq)\ |
|
88 BOOST_PP_SEQ_ELEM(0,seq) (z,n,BOOST_PP_SEQ_ELEM(n,BOOST_PP_SEQ_ELEM(1,seq))) |
|
89 |
|
90 #define BOOST_TYPEOF_SEQ_ENUM_1(seq,macro)\ |
|
91 BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(seq),BOOST_TYPEOF_SEQ_EXPAND_ELEMENT_1,(macro)(seq)) |
|
92 |
|
93 #define BOOST_TYPEOF_SEQ_ENUM_TRAILING_1(seq,macro)\ |
|
94 BOOST_PP_ENUM_TRAILING(BOOST_PP_SEQ_SIZE(seq),BOOST_TYPEOF_SEQ_EXPAND_ELEMENT_1,(macro)(seq)) |
|
95 |
|
96 // |
|
97 |
|
98 #define BOOST_TYPEOF_PLACEHOLDER(z, n, elem)\ |
|
99 BOOST_TYPEOF_VIRTUAL(PLACEHOLDER, elem)(elem) |
|
100 |
|
101 #define BOOST_TYPEOF_PLACEHOLDER_TYPES(z, n, elem)\ |
|
102 BOOST_TYPEOF_VIRTUAL(PLACEHOLDER_TYPES, elem)(elem, n) |
|
103 |
|
104 #define BOOST_TYPEOF_REGISTER_TEMPLATE_ENCODE_PARAM(r, data, n, elem)\ |
|
105 BOOST_TYPEOF_VIRTUAL(ENCODE, elem)(elem, n) |
|
106 |
|
107 #define BOOST_TYPEOF_REGISTER_TEMPLATE_DECODE_PARAM(r, data, n, elem)\ |
|
108 BOOST_TYPEOF_VIRTUAL(DECODE, elem)(elem, n) |
|
109 |
|
110 #define BOOST_TYPEOF_REGISTER_TEMPLATE_PARAM_PAIR(z, n, elem) \ |
|
111 BOOST_TYPEOF_VIRTUAL(EXPANDTYPE, elem)(elem) BOOST_PP_CAT(P, n) |
|
112 |
|
113 #define BOOST_TYPEOF_REGISTER_DEFAULT_TEMPLATE_TYPE(Name,Params,ID)\ |
|
114 Name< BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(Params), P) > |
|
115 |
|
116 //Since we are creating an internal decode struct, we need to use different template names, T instead of P. |
|
117 #define BOOST_TYPEOF_REGISTER_DECODER_TYPE_PARAM_PAIR(z,n,elem) \ |
|
118 BOOST_TYPEOF_VIRTUAL(EXPANDTYPE, elem)(elem) BOOST_PP_CAT(T, n) |
|
119 |
|
120 //Default template param decoding |
|
121 #define BOOST_TYPEOF_TYPEDEF_DECODED_TEMPLATE_TYPE(Name,Params)\ |
|
122 typedef Name<BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(Params),P)> type; |
|
123 |
|
124 //Branch the decoding |
|
125 #define BOOST_TYPEOF_TYPEDEF_DECODED_TYPE(Name,Params)\ |
|
126 BOOST_PP_IF(BOOST_TYPEOF_HAS_TEMPLATES(Params),\ |
|
127 BOOST_TYPEOF_TYPEDEF_DECODED_TEMPLATE_TEMPLATE_TYPE,\ |
|
128 BOOST_TYPEOF_TYPEDEF_DECODED_TEMPLATE_TYPE)(Name,Params) |
|
129 |
|
130 #define BOOST_TYPEOF_REGISTER_TEMPLATE_IMPL(Name, Params, Size, ID)\ |
|
131 BOOST_TYPEOF_BEGIN_ENCODE_NS\ |
|
132 BOOST_TYPEOF_REGISTER_TEMPLATE_TEMPLATE_IMPL(Name, Params, ID)\ |
|
133 template<class V\ |
|
134 BOOST_TYPEOF_SEQ_ENUM_TRAILING(Params, BOOST_TYPEOF_REGISTER_TEMPLATE_PARAM_PAIR)\ |
|
135 >\ |
|
136 struct encode_type_impl<V, Name<BOOST_PP_ENUM_PARAMS(Size, P)> >\ |
|
137 {\ |
|
138 typedef typename boost::type_of::push_back<V, boost::mpl::size_t<ID> >::type V0;\ |
|
139 BOOST_PP_SEQ_FOR_EACH_I(BOOST_TYPEOF_REGISTER_TEMPLATE_ENCODE_PARAM, ~, Params)\ |
|
140 typedef BOOST_PP_CAT(V, Size) type;\ |
|
141 };\ |
|
142 template<class Iter>\ |
|
143 struct decode_type_impl<boost::mpl::size_t<ID>, Iter>\ |
|
144 {\ |
|
145 typedef Iter iter0;\ |
|
146 BOOST_PP_SEQ_FOR_EACH_I(BOOST_TYPEOF_REGISTER_TEMPLATE_DECODE_PARAM, ~, Params)\ |
|
147 BOOST_TYPEOF_TYPEDEF_DECODED_TYPE(Name, Params)\ |
|
148 typedef BOOST_PP_CAT(iter, Size) iter;\ |
|
149 };\ |
|
150 BOOST_TYPEOF_END_ENCODE_NS |
|
151 |
|
152 #endif//BOOST_TYPEOF_TEMPLATE_ENCODING_HPP_INCLUDED |