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