1 /*============================================================================= 2 Copyright (c) 2001-2009 Joel de Guzman 3 Copyright (c) 2005-2006 Dan Marsden 4 Copyright (c) 2009-2011 Christopher Schmidt 5 Copyright (c) 2013-2014 Damien Buhl 6 7 Distributed under the Boost Software License, Version 1.0. (See accompanying 8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 ==============================================================================*/ 10 11 #ifndef BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_BASE_HPP 12 #define BOOST_FUSION_ADAPTED_STRUCT_DETAIL_ADAPT_BASE_HPP 13 14 #include <boost/fusion/support/config.hpp> 15 #include <boost/config.hpp> 16 #include <boost/fusion/support/tag_of_fwd.hpp> 17 #include <boost/fusion/adapted/struct/detail/adapt_auto.hpp> 18 #include <boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp> 19 20 #include <boost/preprocessor/empty.hpp> 21 #include <boost/preprocessor/stringize.hpp> 22 #include <boost/preprocessor/control/if.hpp> 23 #include <boost/preprocessor/seq/size.hpp> 24 #include <boost/preprocessor/seq/for_each.hpp> 25 #include <boost/preprocessor/seq/for_each_i.hpp> 26 #include <boost/preprocessor/seq/enum.hpp> 27 #include <boost/preprocessor/seq/seq.hpp> 28 #include <boost/preprocessor/tuple/eat.hpp> 29 #include <boost/preprocessor/tuple/elem.hpp> 30 #include <boost/preprocessor/arithmetic/dec.hpp> 31 #include <boost/preprocessor/comparison/less.hpp> 32 #include <boost/preprocessor/logical/not.hpp> 33 #include <boost/mpl/bool.hpp> 34 #include <boost/mpl/tag.hpp> 35 #include <boost/mpl/eval_if.hpp> 36 #include <boost/mpl/identity.hpp> 37 #include <boost/type_traits/is_const.hpp> 38 #include <boost/type_traits/add_const.hpp> 39 #include <boost/type_traits/add_reference.hpp> 40 41 #include <boost/typeof/typeof.hpp> 42 43 44 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME_TEMPLATE_PARAMS(SEQ) \ 45 BOOST_PP_SEQ_HEAD(SEQ)<BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TAIL(SEQ))> \ 46 BOOST_PP_EMPTY() 47 48 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(SEQ) \ 49 BOOST_PP_IF( \ 50 BOOST_PP_SEQ_HEAD(SEQ), \ 51 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME_TEMPLATE_PARAMS, \ 52 BOOST_PP_SEQ_HEAD)(BOOST_PP_SEQ_TAIL(SEQ)) 53 54 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL_C(R, _, ELEM) \ 55 (typename ELEM) 56 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL(SEQ) \ 57 BOOST_PP_SEQ_ENUM( \ 58 BOOST_PP_SEQ_FOR_EACH( \ 59 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL_C, \ 60 _, \ 61 BOOST_PP_SEQ_TAIL(SEQ))) 62 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(SEQ) \ 63 BOOST_PP_IF( \ 64 BOOST_PP_SEQ_HEAD(SEQ), \ 65 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL, \ 66 BOOST_PP_TUPLE_EAT(1))(SEQ) 67 68 #ifdef BOOST_MSVC 69 # define BOOST_FUSION_ATTRIBUTE_TYPEOF( \ 70 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 71 \ 72 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \ 73 TEMPLATE_PARAMS_SEQ) \ 74 \ 75 struct deduced_attr_type { \ 76 static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \ 77 typedef \ 78 BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), typename, ) \ 79 BOOST_TYPEOF( PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \ 80 0, ATTRIBUTE)) \ 81 type; \ 82 }; \ 83 \ 84 typedef \ 85 BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), typename, ) \ 86 deduced_attr_type::type attribute_type; 87 88 #else 89 # define BOOST_FUSION_ATTRIBUTE_TYPEOF( \ 90 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 91 \ 92 struct deduced_attr_type { \ 93 static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \ 94 typedef BOOST_TYPEOF( \ 95 PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 0, ATTRIBUTE)) \ 96 type; \ 97 }; \ 98 \ 99 typedef \ 100 BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), typename, ) \ 101 deduced_attr_type::type attribute_type; 102 103 #endif 104 105 #define BOOST_FUSION_ATTRIBUTE_GIVENTYPE( \ 106 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 107 typedef \ 108 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 0, ATTRIBUTE) attribute_type; 109 110 111 #ifdef BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS 112 # define BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 113 MODIFIER, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 114 \ 115 template< \ 116 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 117 > \ 118 struct tag_of< \ 119 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) MODIFIER \ 120 , void \ 121 > \ 122 { \ 123 typedef TAG type; \ 124 }; 125 #else 126 # define BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 127 MODIFIER, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 128 \ 129 template< \ 130 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 131 > \ 132 struct tag_of<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) MODIFIER> \ 133 { \ 134 typedef TAG type; \ 135 }; 136 #endif 137 138 #define BOOST_FUSION_ADAPT_STRUCT_BASE_UNPACK_AND_CALL(R,DATA,I,ATTRIBUTE) \ 139 BOOST_PP_TUPLE_ELEM(4,0,DATA)( \ 140 BOOST_PP_TUPLE_ELEM(4,1,DATA), \ 141 BOOST_PP_TUPLE_ELEM(4,2,DATA), \ 142 BOOST_PP_TUPLE_ELEM(4,3,DATA), \ 143 I, \ 144 ATTRIBUTE) 145 146 #ifdef BOOST_MSVC 147 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAM(R,_,ELEM) \ 148 typedef ELEM ELEM; 149 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS_IMPL(SEQ) \ 150 BOOST_PP_SEQ_FOR_EACH( \ 151 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAM, \ 152 _, \ 153 BOOST_PP_SEQ_TAIL(SEQ)) 154 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS(SEQ) \ 155 BOOST_PP_IF( \ 156 BOOST_PP_SEQ_HEAD(SEQ), \ 157 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS_IMPL, \ 158 BOOST_PP_TUPLE_EAT(1))(SEQ) 159 #else 160 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS(SEQ) 161 #endif 162 163 #define BOOST_FUSION_ADAPT_STRUCT_C_BASE( \ 164 TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW, \ 165 I,PREFIX,ATTRIBUTE,ATTRIBUTE_TUPLE_SIZE, \ 166 DEDUCE_TYPE) \ 167 \ 168 template< \ 169 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 170 > \ 171 struct access::struct_member< \ 172 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 173 , I \ 174 > \ 175 { \ 176 BOOST_PP_IF(DEDUCE_TYPE, \ 177 BOOST_FUSION_ATTRIBUTE_TYPEOF, BOOST_FUSION_ATTRIBUTE_GIVENTYPE)( \ 178 NAME_SEQ, \ 179 ATTRIBUTE, \ 180 ATTRIBUTE_TUPLE_SIZE, \ 181 PREFIX, \ 182 TEMPLATE_PARAMS_SEQ) \ 183 \ 184 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \ 185 TEMPLATE_PARAMS_SEQ) \ 186 \ 187 typedef attribute_type type; \ 188 \ 189 template<typename Seq> \ 190 struct apply \ 191 { \ 192 typedef typename \ 193 add_reference< \ 194 typename mpl::eval_if< \ 195 is_const<Seq> \ 196 , add_const<attribute_type> \ 197 , mpl::identity<attribute_type> \ 198 >::type \ 199 >::type \ 200 type; \ 201 \ 202 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 203 static type \ 204 call(Seq& seq) \ 205 { \ 206 return seq.PREFIX() \ 207 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \ 208 BOOST_PP_NOT(DEDUCE_TYPE), ATTRIBUTE); \ 209 } \ 210 }; \ 211 }; \ 212 \ 213 template< \ 214 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 215 > \ 216 struct struct_member_name< \ 217 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 218 , I \ 219 > \ 220 { \ 221 typedef char const* type; \ 222 \ 223 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 224 static type \ 225 call() \ 226 { \ 227 return BOOST_PP_STRINGIZE( \ 228 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \ 229 BOOST_PP_NOT(DEDUCE_TYPE), ATTRIBUTE)); \ 230 } \ 231 }; 232 233 #define BOOST_FUSION_ADAPT_STRUCT_BASE( \ 234 TEMPLATE_PARAMS_SEQ, \ 235 NAME_SEQ, \ 236 TAG, \ 237 IS_VIEW, \ 238 ATTRIBUTES_SEQ, \ 239 ATTRIBUTES_CALLBACK) \ 240 \ 241 namespace boost \ 242 { \ 243 namespace fusion \ 244 { \ 245 namespace traits \ 246 { \ 247 BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 248 BOOST_PP_EMPTY(), TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 249 BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 250 const, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 251 } \ 252 \ 253 namespace extension \ 254 { \ 255 BOOST_PP_IF( \ 256 BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ)), \ 257 BOOST_PP_SEQ_FOR_EACH_I_R, \ 258 BOOST_PP_TUPLE_EAT(4))( \ 259 1, \ 260 BOOST_FUSION_ADAPT_STRUCT_BASE_UNPACK_AND_CALL, \ 261 (ATTRIBUTES_CALLBACK,TEMPLATE_PARAMS_SEQ,NAME_SEQ, IS_VIEW),\ 262 BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ)) \ 263 \ 264 template< \ 265 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 266 TEMPLATE_PARAMS_SEQ) \ 267 > \ 268 struct struct_size<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)> \ 269 : mpl::int_<BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ))> \ 270 {}; \ 271 \ 272 template< \ 273 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 274 TEMPLATE_PARAMS_SEQ) \ 275 > \ 276 struct struct_is_view< \ 277 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 278 > \ 279 : mpl::BOOST_PP_IIF(IS_VIEW,true_,false_) \ 280 {}; \ 281 } \ 282 } \ 283 \ 284 namespace mpl \ 285 { \ 286 template<typename> \ 287 struct sequence_tag; \ 288 \ 289 template< \ 290 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 291 TEMPLATE_PARAMS_SEQ) \ 292 > \ 293 struct sequence_tag<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)> \ 294 { \ 295 typedef fusion::fusion_sequence_tag type; \ 296 }; \ 297 \ 298 template< \ 299 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 300 TEMPLATE_PARAMS_SEQ) \ 301 > \ 302 struct sequence_tag< \ 303 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) const \ 304 > \ 305 { \ 306 typedef fusion::fusion_sequence_tag type; \ 307 }; \ 308 } \ 309 } 310 311 #endif 312