1 /*============================================================================= 2 Copyright (c) 2001-2009 Joel de Guzman 3 Copyright (c) 2005-2006 Dan Marsden 4 Copyright (c) 2010 Christopher Schmidt 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 ==============================================================================*/ 9 10 #ifndef BOOST_FUSION_ADAPTED_ADT_DETAIL_ADAPT_BASE_HPP 11 #define BOOST_FUSION_ADAPTED_ADT_DETAIL_ADAPT_BASE_HPP 12 13 #include <boost/fusion/support/config.hpp> 14 #include <boost/fusion/adapted/struct/detail/adapt_auto.hpp> 15 #include <boost/fusion/adapted/struct/detail/adapt_is_tpl.hpp> 16 17 #include <boost/preprocessor/control/if.hpp> 18 #include <boost/preprocessor/control/expr_if.hpp> 19 #include <boost/preprocessor/seq/seq.hpp> 20 #include <boost/preprocessor/seq/elem.hpp> 21 #include <boost/preprocessor/tuple/elem.hpp> 22 #include <boost/mpl/if.hpp> 23 #include <boost/type_traits/is_const.hpp> 24 #include <boost/type_traits/remove_const.hpp> 25 #include <boost/type_traits/remove_reference.hpp> 26 27 #include <boost/typeof/typeof.hpp> 28 29 #define BOOST_FUSION_ADAPT_ADT_GET_IDENTITY_TEMPLATE_IMPL(TEMPLATE_PARAMS_SEQ) \ 30 typename detail::get_identity< \ 31 lvalue \ 32 , BOOST_PP_SEQ_ELEM(1,TEMPLATE_PARAMS_SEQ) \ 33 >::type 34 35 #define BOOST_FUSION_ADAPT_ADT_GET_IDENTITY_NON_TEMPLATE_IMPL( \ 36 TEMPLATE_PARAMS_SEQ) \ 37 \ 38 boost::remove_const<boost::remove_reference<lvalue>::type>::type 39 40 #define BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR(ATTRIBUTE, \ 41 ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE) \ 42 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \ 43 BOOST_PP_IF(DEDUCE_TYPE, 0, 2), ATTRIBUTE) 44 45 #define BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_SETEXPR(ATTRIBUTE, \ 46 ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE) \ 47 BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, \ 48 BOOST_PP_IF(DEDUCE_TYPE, 1, 3), ATTRIBUTE) 49 50 #ifdef BOOST_MSVC 51 # define BOOST_FUSION_DEDUCED_ATTR_TYPE(NAME_SEQ, ATTRIBUTE, \ 52 ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 53 \ 54 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \ 55 TEMPLATE_PARAMS_SEQ) \ 56 \ 57 struct deduced_attr_type { \ 58 static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \ 59 typedef \ 60 BOOST_PP_EXPR_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), \ 61 typename) \ 62 BOOST_TYPEOF( PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR( \ 63 ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, 1)) type; \ 64 }; 65 66 #else 67 # define BOOST_FUSION_DEDUCED_ATTR_TYPE(NAME_SEQ, ATTRIBUTE, \ 68 ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 69 struct deduced_attr_type { \ 70 static const BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj; \ 71 typedef BOOST_TYPEOF( PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR( \ 72 ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, 1)) type; \ 73 }; 74 75 #endif 76 77 #define BOOST_FUSION_ADT_ATTRIBUTE_TYPEOF( \ 78 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 79 \ 80 BOOST_FUSION_DEDUCED_ATTR_TYPE( \ 81 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 82 \ 83 typedef \ 84 BOOST_PP_EXPR_IF(BOOST_FUSION_ADAPT_IS_TPL(TEMPLATE_PARAMS_SEQ), \ 85 typename) \ 86 deduced_attr_type::type type; \ 87 typedef type const_type; 88 89 #define BOOST_FUSION_ADT_ATTRIBUTE_GIVENTYPE( \ 90 NAME_SEQ, ATTRIBUTE, ATTRIBUTE_TUPLE_SIZE, PREFIX, TEMPLATE_PARAMS_SEQ) \ 91 \ 92 typedef BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 0, ATTRIBUTE) type; \ 93 typedef BOOST_PP_TUPLE_ELEM(ATTRIBUTE_TUPLE_SIZE, 1, ATTRIBUTE) const_type; 94 95 96 #define BOOST_FUSION_ADAPT_ADT_C_BASE( \ 97 TEMPLATE_PARAMS_SEQ,NAME_SEQ,I,PREFIX, \ 98 ATTRIBUTE,ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE) \ 99 \ 100 template< \ 101 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 102 > \ 103 struct access::adt_attribute_access< \ 104 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 105 , I \ 106 > \ 107 { \ 108 \ 109 BOOST_PP_IF(DEDUCE_TYPE, \ 110 BOOST_FUSION_ADT_ATTRIBUTE_TYPEOF, \ 111 BOOST_FUSION_ADT_ATTRIBUTE_GIVENTYPE)( \ 112 NAME_SEQ, \ 113 ATTRIBUTE, \ 114 ATTRIBUTE_TUPLE_SIZE, \ 115 PREFIX, \ 116 TEMPLATE_PARAMS_SEQ) \ 117 \ 118 template<class Val> \ 119 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 120 static void \ 121 boost_fusion_adapt_adt_impl_set( \ 122 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj, \ 123 Val const& val) \ 124 { \ 125 PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_SETEXPR(ATTRIBUTE, \ 126 ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE); \ 127 } \ 128 \ 129 BOOST_FUSION_GPU_ENABLED \ 130 static type \ 131 boost_fusion_adapt_adt_impl_get( \ 132 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& obj) \ 133 { \ 134 return PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR(ATTRIBUTE, \ 135 ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE); \ 136 } \ 137 \ 138 BOOST_FUSION_GPU_ENABLED \ 139 static const_type \ 140 boost_fusion_adapt_adt_impl_get( \ 141 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) const& obj) \ 142 { \ 143 return PREFIX() BOOST_FUSION_ADAPT_ADT_ATTRIBUTE_GETEXPR(ATTRIBUTE, \ 144 ATTRIBUTE_TUPLE_SIZE, DEDUCE_TYPE); \ 145 } \ 146 }; \ 147 \ 148 template< \ 149 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 150 > \ 151 struct adt_attribute_proxy< \ 152 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 153 , I \ 154 , true \ 155 > \ 156 { \ 157 typedef \ 158 BOOST_PP_EXPR_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), typename) \ 159 access::adt_attribute_access< \ 160 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 161 , I \ 162 >::const_type type; \ 163 \ 164 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 165 explicit \ 166 adt_attribute_proxy( \ 167 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) const& o) \ 168 : obj(&o) \ 169 {} \ 170 \ 171 BOOST_FUSION_GPU_ENABLED \ 172 type get() const \ 173 { \ 174 return access::adt_attribute_access< \ 175 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 176 , I \ 177 >::boost_fusion_adapt_adt_impl_get(*obj); \ 178 } \ 179 \ 180 BOOST_FUSION_GPU_ENABLED \ 181 operator type() const \ 182 { \ 183 return get(); \ 184 } \ 185 \ 186 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) const* obj; \ 187 }; \ 188 \ 189 template< \ 190 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 191 > \ 192 struct adt_attribute_proxy< \ 193 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 194 , I \ 195 , false \ 196 > \ 197 { \ 198 typedef \ 199 BOOST_PP_EXPR_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), typename) \ 200 access::adt_attribute_access< \ 201 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 202 , I \ 203 >::type type; \ 204 \ 205 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 206 explicit \ 207 adt_attribute_proxy( \ 208 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)& o) \ 209 : obj(&o) \ 210 {} \ 211 \ 212 template<class Val> \ 213 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 214 adt_attribute_proxy& \ 215 operator=(Val const& val) \ 216 { \ 217 access::adt_attribute_access< \ 218 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 219 , I \ 220 >::boost_fusion_adapt_adt_impl_set(*obj, val); \ 221 return *this; \ 222 } \ 223 \ 224 BOOST_FUSION_GPU_ENABLED \ 225 type get() const \ 226 { \ 227 return access::adt_attribute_access< \ 228 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 229 , I \ 230 >::boost_fusion_adapt_adt_impl_get(*obj); \ 231 } \ 232 \ 233 BOOST_FUSION_GPU_ENABLED \ 234 operator type() const \ 235 { \ 236 return get(); \ 237 } \ 238 \ 239 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ)* obj; \ 240 }; \ 241 \ 242 template< \ 243 BOOST_FUSION_ADAPT_STRUCT_UNPACK_TEMPLATE_PARAMS(TEMPLATE_PARAMS_SEQ) \ 244 > \ 245 struct access::struct_member< \ 246 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 247 , I \ 248 > \ 249 { \ 250 typedef BOOST_PP_EXPR_IF(BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), \ 251 typename) \ 252 adt_attribute_proxy< \ 253 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 254 , I \ 255 , false \ 256 >::type lvalue; \ 257 \ 258 BOOST_FUSION_ADAPT_STRUCT_MSVC_REDEFINE_TEMPLATE_PARAMS( \ 259 TEMPLATE_PARAMS_SEQ) \ 260 \ 261 typedef \ 262 BOOST_PP_IF( \ 263 BOOST_PP_SEQ_HEAD(TEMPLATE_PARAMS_SEQ), \ 264 BOOST_FUSION_ADAPT_ADT_GET_IDENTITY_TEMPLATE_IMPL, \ 265 BOOST_FUSION_ADAPT_ADT_GET_IDENTITY_NON_TEMPLATE_IMPL)( \ 266 TEMPLATE_PARAMS_SEQ) \ 267 type; \ 268 \ 269 template<typename Seq> \ 270 struct apply \ 271 { \ 272 typedef \ 273 adt_attribute_proxy< \ 274 BOOST_FUSION_ADAPT_STRUCT_UNPACK_NAME(NAME_SEQ) \ 275 , I \ 276 , is_const<Seq>::value \ 277 > \ 278 type; \ 279 \ 280 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED \ 281 static type \ 282 call(Seq& obj) \ 283 { \ 284 return type(obj); \ 285 } \ 286 }; \ 287 }; 288 289 #endif 290