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