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/mpl/bool.hpp> 33 #include <boost/mpl/tag.hpp> 34 #include <boost/mpl/eval_if.hpp> 35 #include <boost/mpl/identity.hpp> 36 #include <boost/type_traits/add_const.hpp> 37 38 #include <boost/typeof/typeof.hpp> 39 40 41 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME_TEMPLATE_PARAMS(SEQ) \ 42 BOOST_PP_SEQ_HEAD(SEQ)<BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TAIL(SEQ))> \ 43 BOOST_PP_EMPTY() 44 45 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(SEQ) \ 46 BOOST_PP_IF( \ 47 BOOST_PP_SEQ_HEAD(SEQ), \ 48 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME_TEMPLATE_PARAMS, \ 49 BOOST_PP_SEQ_HEAD)(BOOST_PP_SEQ_TAIL(SEQ)) 50 51 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL_C(R, _, ELEM) \ 52 (typename ELEM) 53 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL(SEQ) \ 54 BOOST_PP_SEQ_ENUM( \ 55 BOOST_PP_SEQ_FOR_EACH( \ 56 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL_C, \ 57 _, \ 58 BOOST_PP_SEQ_TAIL(SEQ))) 59 #define BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(SEQ) \ 60 BOOST_PP_IF( \ 61 BOOST_PP_SEQ_HEAD(SEQ), \ 62 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS_IMPL, \ 63 BOOST_PP_TUPLE_EAT(1))(SEQ) 64 65 #ifdef BOOST_MSVC 66 # define BOOST_FUSION_ATTRIBUTE_TYPEOF( \ 67 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 68 \ 69 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \ 70 TEMPLATE_PARAMS_SEQ) \ 71 \ 72 struct deduced_attr_type { \ 73 static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \ 74 typedef \ 75 BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), typename, ) \ 76 BOOST_TYPEOF( PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \ 77 0, ATTRIBUTE)) \ 78 type; \ 79 }; \ 80 \ 81 typedef \ 82 BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), typename, ) \ 83 deduced_attr_type::type attribute_type; 84 85 #else 86 # define BOOST_FUSION_ATTRIBUTE_TYPEOF( \ 87 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 88 \ 89 struct deduced_attr_type { \ 90 static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \ 91 typedef BOOST_TYPEOF( \ 92 PREFIX() obj.BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, 0, ATTRIBUTE)) \ 93 type; \ 94 }; \ 95 \ 96 typedef \ 97 BOOST_PP_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), typename, ) \ 98 deduced_attr_type::type attribute_type; 99 100 #endif 101 102 #define BOOST_FUSION_ATTRIBUTE_GIVENTYPE( \ 103 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPEL_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 104 typedef \ 105 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, 0, ATTRIBUTE) attribute_type; 106 107 108 #ifdef BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS 109 # define BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 110 MODIFIER, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 111 \ 112 template< \ 113 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 114 > \ 115 struct tag_of< \ 116 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) MODIFIER \ 117 , void \ 118 > \ 119 { \ 120 typedef TAG type; \ 121 }; 122 #else 123 # define BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 124 MODIFIER, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 125 \ 126 template< \ 127 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 128 > \ 129 struct tag_of<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) MODIFIER> \ 130 { \ 131 typedef TAG type; \ 132 }; 133 #endif 134 135 #define BOOST_FUSION_ADAPT_STRUCT_BASE_UNPACK_AND_CALL(R,DATA,I,ATTRIBUTE) \ 136 BOOST_PP_TUPLE_ELEM(4,0,DATA)( \ 137 BOOST_PP_TUPLE_ELEM(4,1,DATA), \ 138 BOOST_PP_TUPLE_ELEM(4,2,DATA), \ 139 BOOST_PP_TUPLE_ELEM(4,3,DATA), \ 140 I, \ 141 ATTRIBUTE) 142 143 #ifdef BOOST_MSVC 144 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAM(R,_,ELEM) \ 145 typedef ELEM ELEM; 146 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS_IMPL(SEQ) \ 147 BOOST_PP_SEQ_FOR_EACH( \ 148 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAM, \ 149 _, \ 150 BOOST_PP_SEQ_TAIL(SEQ)) 151 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS(SEQ) \ 152 BOOST_PP_IF( \ 153 BOOST_PP_SEQ_HEAD(SEQ), \ 154 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS_IMPL, \ 155 BOOST_PP_TUPLE_EAT(1))(SEQ) 156 #else 157 # define BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS(SEQ) 158 #endif 159 160 #define BOOST_FUSION_ADAPT_STRUCT_C_BASE( \ 161 TEMPLATE_PARAMS_SEQ,NAME_SEQ,IS_VIEW, \ 162 I,PREFIX,ATTRIBUTE,ATTRIBUTE_TUPEL_SIZE, \ 163 DEDUCE_TYPE) \ 164 \ 165 template< \ 166 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 167 > \ 168 struct access::struct_member< \ 169 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 170 , I \ 171 > \ 172 { \ 173 BOOST_PP_IF(DEDUCE_TYPE, \ 174 BOOST_FUSION_ATTRIBUTE_TYPEOF, BOOST_FUSION_ATTRIBUTE_GIVENTYPE)( \ 175 NAME_SEQ, \ 176 ATTRIBUTE, \ 177 ATTRIBUTE_TUPEL_SIZE, \ 178 PREFIX, \ 179 TEMPLATE_PARAMS_SEQ) \ 180 \ 181 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \ 182 TEMPLATE_PARAMS_SEQ) \ 183 \ 184 typedef attribute_type type; \ 185 \ 186 template<typename Seq> \ 187 struct apply \ 188 { \ 189 typedef typename \ 190 add_reference< \ 191 typename mpl::eval_if< \ 192 is_const<Seq> \ 193 , add_const<attribute_type> \ 194 , mpl::identity<attribute_type> \ 195 >::type \ 196 >::type \ 197 type; \ 198 \ 199 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 200 static type \ 201 call(Seq& seq) \ 202 { \ 203 return seq.PREFIX() \ 204 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \ 205 BOOST_PP_IF(DEDUCE_TYPE, 0, 1), ATTRIBUTE); \ 206 } \ 207 }; \ 208 }; \ 209 \ 210 template< \ 211 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 212 > \ 213 struct struct_member_name< \ 214 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 215 , I \ 216 > \ 217 { \ 218 typedef char const* type; \ 219 \ 220 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 221 static type \ 222 call() \ 223 { \ 224 return BOOST_PP_STRINGIZE( \ 225 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPEL_SIZE, \ 226 BOOST_PP_IF(DEDUCE_TYPE, 0, 1), \ 227 ATTRIBUTE)); \ 228 } \ 229 }; 230 231 #define BOOST_FUSION_ADAPT_STRUCT_BASE( \ 232 TEMPLATE_PARAMS_SEQ, \ 233 NAME_SEQ, \ 234 TAG, \ 235 IS_VIEW, \ 236 ATTRIBUTES_SEQ, \ 237 ATTRIBUTES_CALLBACK) \ 238 \ 239 namespace boost \ 240 { \ 241 namespace fusion \ 242 { \ 243 namespace traits \ 244 { \ 245 BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 246 BOOST_PP_EMPTY(), TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 247 BOOST_FUSION_ADAPT_STRUCT_TAG_OF_SPECIALIZATION( \ 248 const, TEMPLATE_PARAMS_SEQ, NAME_SEQ, TAG) \ 249 } \ 250 \ 251 namespace extension \ 252 { \ 253 BOOST_PP_IF( \ 254 BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ)), \ 255 BOOST_PP_SEQ_FOR_EACH_I_R, \ 256 BOOST_PP_TUPLE_EAT(4))( \ 257 1, \ 258 BOOST_FUSION_ADAPT_STRUCT_BASE_UNPACK_AND_CALL, \ 259 (ATTRIBUTES_CALLBACK,TEMPLATE_PARAMS_SEQ,NAME_SEQ, IS_VIEW),\ 260 BOOST_PP_SEQ_TAIL(ATTRIBUTES_SEQ)) \ 261 \ 262 template< \ 263 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 264 TEMPLATE_PARAMS_SEQ) \ 265 > \ 266 struct struct_size<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)> \ 267 : mpl::int_<BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ))> \ 268 {}; \ 269 \ 270 template< \ 271 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 272 TEMPLATE_PARAMS_SEQ) \ 273 > \ 274 struct struct_is_view< \ 275 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 276 > \ 277 : mpl::BOOST_PP_IF(IS_VIEW,true_,false_) \ 278 {}; \ 279 } \ 280 } \ 281 \ 282 namespace mpl \ 283 { \ 284 template<typename> \ 285 struct sequence_tag; \ 286 \ 287 template< \ 288 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 289 TEMPLATE_PARAMS_SEQ) \ 290 > \ 291 struct sequence_tag<BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)> \ 292 { \ 293 typedef fusion::fusion_sequence_tag type; \ 294 }; \ 295 \ 296 template< \ 297 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS( \ 298 TEMPLATE_PARAMS_SEQ) \ 299 > \ 300 struct sequence_tag< \ 301 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) const \ 302 > \ 303 { \ 304 typedef fusion::fusion_sequence_tag type; \ 305 }; \ 306 } \ 307 } 308 309 #endif 310