1 //  Copyright (c) 2001-2011 Hartmut Kaiser
2 //
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 #if !defined(BOOST_SPIRIT_ADAPT_ADT_ATTRIBUTES_SEP_15_2010_1219PM)
7 #define BOOST_SPIRIT_ADAPT_ADT_ATTRIBUTES_SEP_15_2010_1219PM
8 
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12 
13 #include <boost/spirit/home/support/attributes.hpp>
14 #include <boost/spirit/home/support/container.hpp>
15 #include <boost/spirit/home/support/numeric_traits.hpp>
16 #include <boost/fusion/include/adapt_adt.hpp>
17 #include <boost/utility/enable_if.hpp>
18 
19 ///////////////////////////////////////////////////////////////////////////////
20 // customization points allowing to use adapted classes with spirit
21 namespace boost { namespace spirit { namespace traits
22 {
23     ///////////////////////////////////////////////////////////////////////////
24     template <typename T, int N, bool Const, typename Domain>
25     struct not_is_variant<
26             fusion::extension::adt_attribute_proxy<T, N, Const>, Domain>
27       : not_is_variant<
28             typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
29           , Domain>
30     {};
31 
32     template <typename T, int N, bool Const, typename Domain>
33     struct not_is_optional<
34             fusion::extension::adt_attribute_proxy<T, N, Const>, Domain>
35       : not_is_optional<
36             typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
37           , Domain>
38     {};
39 
40     ///////////////////////////////////////////////////////////////////////////
41     template <typename T, int N, bool Const>
42     struct is_container<fusion::extension::adt_attribute_proxy<T, N, Const> >
43       : is_container<
44             typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
45         >
46     {};
47 
48     template <typename T, int N, bool Const>
49     struct container_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
50       : container_value<
51             typename remove_reference<
52                 typename fusion::extension::adt_attribute_proxy<
53                     T, N, Const
54                 >::type
55             >::type
56         >
57     {};
58 
59     template <typename T, int N, bool Const>
60     struct container_value<
61             fusion::extension::adt_attribute_proxy<T, N, Const> const>
62       : container_value<
63             typename add_const<
64                 typename remove_reference<
65                     typename fusion::extension::adt_attribute_proxy<
66                         T, N, Const
67                     >::type
68                 >::type
69             >::type
70         >
71     {};
72 
73     template <typename T, int N, typename Val>
74     struct push_back_container<
75         fusion::extension::adt_attribute_proxy<T, N, false>
76       , Val
77       , typename enable_if<is_reference<
78             typename fusion::extension::adt_attribute_proxy<T, N, false>::type
79         > >::type>
80     {
callboost::spirit::traits::push_back_container81         static bool call(
82             fusion::extension::adt_attribute_proxy<T, N, false>& p
83           , Val const& val)
84         {
85             typedef typename
86                 fusion::extension::adt_attribute_proxy<T, N, false>::type
87             type;
88             return push_back(type(p), val);
89         }
90     };
91 
92     template <typename T, int N, bool Const>
93     struct container_iterator<
94             fusion::extension::adt_attribute_proxy<T, N, Const> >
95       : container_iterator<
96             typename remove_reference<
97                 typename fusion::extension::adt_attribute_proxy<
98                     T, N, Const
99                 >::type
100             >::type
101         >
102     {};
103 
104     template <typename T, int N, bool Const>
105     struct container_iterator<
106             fusion::extension::adt_attribute_proxy<T, N, Const> const>
107       : container_iterator<
108             typename add_const<
109                 typename remove_reference<
110                     typename fusion::extension::adt_attribute_proxy<
111                         T, N, Const
112                     >::type
113                 >::type
114             >::type
115         >
116     {};
117 
118     template <typename T, int N, bool Const>
119     struct begin_container<fusion::extension::adt_attribute_proxy<T, N, Const> >
120     {
121         typedef typename remove_reference<
122             typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
123         >::type container_type;
124 
125         static typename container_iterator<container_type>::type
callboost::spirit::traits::begin_container126         call(fusion::extension::adt_attribute_proxy<T, N, Const>& c)
127         {
128             return c.get().begin();
129         }
130     };
131 
132     template <typename T, int N, bool Const>
133     struct begin_container<fusion::extension::adt_attribute_proxy<T, N, Const> const>
134     {
135         typedef typename add_const<
136             typename remove_reference<
137                 typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
138             >::type
139         >::type container_type;
140 
141         static typename container_iterator<container_type>::type
callboost::spirit::traits::begin_container142         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& c)
143         {
144             return c.get().begin();
145         }
146     };
147 
148     template <typename T, int N, bool Const>
149     struct end_container<fusion::extension::adt_attribute_proxy<T, N, Const> >
150     {
151         typedef typename remove_reference<
152             typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
153         >::type container_type;
154 
155         static typename container_iterator<container_type>::type
callboost::spirit::traits::end_container156         call(fusion::extension::adt_attribute_proxy<T, N, Const>& c)
157         {
158             return c.get().end();
159         }
160     };
161 
162     template <typename T, int N, bool Const>
163     struct end_container<fusion::extension::adt_attribute_proxy<T, N, Const> const>
164     {
165         typedef typename add_const<
166             typename remove_reference<
167                 typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
168             >::type
169         >::type container_type;
170 
171         static typename container_iterator<container_type>::type
callboost::spirit::traits::end_container172         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& c)
173         {
174             return c.get().end();
175         }
176     };
177 
178     ///////////////////////////////////////////////////////////////////////////
179     template <typename T, int N, typename Val>
180     struct assign_to_attribute_from_value<
181         fusion::extension::adt_attribute_proxy<T, N, false>
182       , Val>
183     {
184         static void
callboost::spirit::traits::assign_to_attribute_from_value185         call(Val const& val
186           , fusion::extension::adt_attribute_proxy<T, N, false>& attr)
187         {
188             attr = val;
189         }
190     };
191 
192     template <typename T, int N, bool Const, typename Exposed>
193     struct extract_from_attribute<
194         fusion::extension::adt_attribute_proxy<T, N, Const>, Exposed>
195     {
196         typedef
197             typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
198         get_return_type;
199         typedef typename remove_const<
200             typename remove_reference<
201                 get_return_type
202             >::type
203         >::type embedded_type;
204         typedef
205             typename spirit::result_of::extract_from<Exposed, embedded_type>::type
206         extracted_type;
207 
208         // If adt_attribute_proxy returned a value we must pass the attribute
209         // by value, otherwise we will end up with a reference to a temporary
210         // that will expire out of scope of the function call.
211         typedef typename mpl::if_c<is_reference<get_return_type>::value
212           , extracted_type
213           , typename remove_reference<extracted_type>::type
214         >::type type;
215 
216         template <typename Context>
217         static type
callboost::spirit::traits::extract_from_attribute218         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val, Context& ctx)
219         {
220             return extract_from<Exposed>(val.get(), ctx);
221         }
222     };
223 
224     ///////////////////////////////////////////////////////////////////////////
225     template <typename T, int N, bool Const>
226     struct attribute_type<fusion::extension::adt_attribute_proxy<T, N, Const> >
227       : fusion::extension::adt_attribute_proxy<T, N, Const>
228     {};
229 
230     ///////////////////////////////////////////////////////////////////////////
231     template <typename T, int N, bool Const>
232     struct optional_attribute<
233         fusion::extension::adt_attribute_proxy<T, N, Const> >
234     {
235         typedef typename result_of::optional_value<
236             typename remove_reference<
237                 typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
238             >::type
239         >::type type;
240 
241         static type
callboost::spirit::traits::optional_attribute242         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
243         {
244             return optional_value(val.get());
245         }
246 
247         static bool
is_validboost::spirit::traits::optional_attribute248         is_valid(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
249         {
250             return has_optional_value(val.get());
251         }
252     };
253 
254     ///////////////////////////////////////////////////////////////////////////
255     template <typename T, int N, typename Attribute, typename Domain>
256     struct transform_attribute<
257         fusion::extension::adt_attribute_proxy<T, N, false>
258       , Attribute
259       , Domain
260       , typename disable_if<is_reference<
261             typename fusion::extension::adt_attribute_proxy<T, N, false>::type
262         > >::type>
263     {
264         typedef Attribute type;
265 
266         static Attribute
preboost::spirit::traits::transform_attribute267         pre(fusion::extension::adt_attribute_proxy<T, N, false>& val)
268         {
269             return val;
270         }
271         static void
postboost::spirit::traits::transform_attribute272         post(
273             fusion::extension::adt_attribute_proxy<T, N, false>& val
274           , Attribute const& attr)
275         {
276             val = attr;
277         }
278         static void
failboost::spirit::traits::transform_attribute279         fail(fusion::extension::adt_attribute_proxy<T, N, false>&)
280         {
281         }
282     };
283 
284     template <
285         typename T, int N, bool Const, typename Attribute, typename Domain>
286     struct transform_attribute<
287         fusion::extension::adt_attribute_proxy<T, N, Const>
288       , Attribute
289       , Domain
290       , typename enable_if<is_reference<
291             typename fusion::extension::adt_attribute_proxy<
292                 T, N, Const
293             >::type
294         > >::type>
295     {
296         typedef Attribute& type;
297 
298         static Attribute&
preboost::spirit::traits::transform_attribute299         pre(fusion::extension::adt_attribute_proxy<T, N, Const>& val)
300         {
301             return val;
302         }
303         static void
postboost::spirit::traits::transform_attribute304         post(
305             fusion::extension::adt_attribute_proxy<T, N, Const>&
306           , Attribute const&)
307         {
308         }
309         static void
failboost::spirit::traits::transform_attribute310         fail(fusion::extension::adt_attribute_proxy<T, N, Const>&)
311         {
312         }
313     };
314 
315     template <typename T, int N, bool Const>
316     struct clear_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
317     {
callboost::spirit::traits::clear_value318         static void call(
319             fusion::extension::adt_attribute_proxy<T, N, Const>& val)
320         {
321             typedef typename
322                 fusion::extension::adt_attribute_proxy<T, N, Const>::type
323             type;
324             clear(type(val));
325         }
326     };
327 
328     template <typename T, int N, bool Const>
329     struct attribute_size<fusion::extension::adt_attribute_proxy<T, N, Const> >
330     {
331         typedef typename remove_const<
332             typename remove_reference<
333                 typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
334             >::type
335         >::type embedded_type;
336 
337         typedef typename attribute_size<embedded_type>::type type;
338 
339         static type
callboost::spirit::traits::attribute_size340         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
341         {
342             return attribute_size<embedded_type>::call(val.get());
343         }
344     };
345 
346     ///////////////////////////////////////////////////////////////////////////
347     // customization point specializations for numeric generators
348     template <typename T, int N, bool Const>
349     struct absolute_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
350     {
351         typedef typename
352             fusion::extension::adt_attribute_proxy<T, N, Const>::type
353         type;
354 
355         static type
callboost::spirit::traits::absolute_value356         call (fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
357         {
358             return get_absolute_value(val.get());
359         }
360     };
361 
362     template <typename T, int N, bool Const>
363     struct is_negative<fusion::extension::adt_attribute_proxy<T, N, Const> >
364     {
365         static bool
callboost::spirit::traits::is_negative366         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
367         {
368             return test_negative(val.get());
369         }
370     };
371 
372     template <typename T, int N, bool Const>
373     struct is_zero<fusion::extension::adt_attribute_proxy<T, N, Const> >
374     {
375         static bool
callboost::spirit::traits::is_zero376         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
377         {
378             return test_zero(val.get());
379         }
380     };
381 
382     template <typename T, int N, bool Const>
383     struct is_nan<fusion::extension::adt_attribute_proxy<T, N, Const> >
384     {
385         static bool
callboost::spirit::traits::is_nan386         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
387         {
388             return test_nan(val.get());
389         }
390     };
391 
392     template <typename T, int N, bool Const>
393     struct is_infinite<fusion::extension::adt_attribute_proxy<T, N, Const> >
394     {
395         static bool
callboost::spirit::traits::is_infinite396         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
397         {
398             return test_infinite(val.get());
399         }
400     };
401 }}}
402 
403 ///////////////////////////////////////////////////////////////////////////////
404 namespace boost { namespace spirit { namespace result_of
405 {
406     template <typename T, int N, bool Const>
407     struct optional_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
408       : result_of::optional_value<
409             typename remove_const<
410                 typename remove_reference<
411                     typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
412                 >::type
413             >::type>
414     {};
415 }}}
416 
417 #endif
418