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 typename remove_const<
197             typename remove_reference<
198                 typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
199             >::type
200         >::type embedded_type;
201         typedef
202             typename spirit::result_of::extract_from<Exposed, embedded_type>::type
203         type;
204 
205         template <typename Context>
206         static type
callboost::spirit::traits::extract_from_attribute207         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val, Context& ctx)
208         {
209             return extract_from<Exposed>(val.get(), ctx);
210         }
211     };
212 
213     ///////////////////////////////////////////////////////////////////////////
214     template <typename T, int N, bool Const>
215     struct attribute_type<fusion::extension::adt_attribute_proxy<T, N, Const> >
216       : fusion::extension::adt_attribute_proxy<T, N, Const>
217     {};
218 
219     ///////////////////////////////////////////////////////////////////////////
220     template <typename T, int N, bool Const>
221     struct optional_attribute<
222         fusion::extension::adt_attribute_proxy<T, N, Const> >
223     {
224         typedef typename result_of::optional_value<
225             typename remove_reference<
226                 typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
227             >::type
228         >::type type;
229 
230         static type
callboost::spirit::traits::optional_attribute231         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
232         {
233             return optional_value(val.get());
234         }
235 
236         static bool
is_validboost::spirit::traits::optional_attribute237         is_valid(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
238         {
239             return has_optional_value(val.get());
240         }
241     };
242 
243     ///////////////////////////////////////////////////////////////////////////
244     template <typename T, int N, typename Attribute, typename Domain>
245     struct transform_attribute<
246         fusion::extension::adt_attribute_proxy<T, N, false>
247       , Attribute
248       , Domain
249       , typename disable_if<is_reference<
250             typename fusion::extension::adt_attribute_proxy<T, N, false>::type
251         > >::type>
252     {
253         typedef Attribute type;
254 
255         static Attribute
preboost::spirit::traits::transform_attribute256         pre(fusion::extension::adt_attribute_proxy<T, N, false>& val)
257         {
258             return val;
259         }
260         static void
postboost::spirit::traits::transform_attribute261         post(
262             fusion::extension::adt_attribute_proxy<T, N, false>& val
263           , Attribute const& attr)
264         {
265             val = attr;
266         }
267         static void
failboost::spirit::traits::transform_attribute268         fail(fusion::extension::adt_attribute_proxy<T, N, false>&)
269         {
270         }
271     };
272 
273     template <
274         typename T, int N, bool Const, typename Attribute, typename Domain>
275     struct transform_attribute<
276         fusion::extension::adt_attribute_proxy<T, N, Const>
277       , Attribute
278       , Domain
279       , typename enable_if<is_reference<
280             typename fusion::extension::adt_attribute_proxy<
281                 T, N, Const
282             >::type
283         > >::type>
284     {
285         typedef Attribute& type;
286 
287         static Attribute&
preboost::spirit::traits::transform_attribute288         pre(fusion::extension::adt_attribute_proxy<T, N, Const>& val)
289         {
290             return val;
291         }
292         static void
postboost::spirit::traits::transform_attribute293         post(
294             fusion::extension::adt_attribute_proxy<T, N, Const>&
295           , Attribute const&)
296         {
297         }
298         static void
failboost::spirit::traits::transform_attribute299         fail(fusion::extension::adt_attribute_proxy<T, N, Const>&)
300         {
301         }
302     };
303 
304     template <typename T, int N, bool Const>
305     struct clear_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
306     {
callboost::spirit::traits::clear_value307         static void call(
308             fusion::extension::adt_attribute_proxy<T, N, Const>& val)
309         {
310             typedef typename
311                 fusion::extension::adt_attribute_proxy<T, N, Const>::type
312             type;
313             clear(type(val));
314         }
315     };
316 
317     template <typename T, int N, bool Const>
318     struct attribute_size<fusion::extension::adt_attribute_proxy<T, N, Const> >
319     {
320         typedef typename remove_const<
321             typename remove_reference<
322                 typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
323             >::type
324         >::type embedded_type;
325 
326         typedef typename attribute_size<embedded_type>::type type;
327 
328         static type
callboost::spirit::traits::attribute_size329         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
330         {
331             return attribute_size<embedded_type>::call(val.get());
332         }
333     };
334 
335     ///////////////////////////////////////////////////////////////////////////
336     // customization point specializations for numeric generators
337     template <typename T, int N, bool Const>
338     struct absolute_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
339     {
340         typedef typename
341             fusion::extension::adt_attribute_proxy<T, N, Const>::type
342         type;
343 
344         static type
callboost::spirit::traits::absolute_value345         call (fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
346         {
347             return get_absolute_value(val.get());
348         }
349     };
350 
351     template <typename T, int N, bool Const>
352     struct is_negative<fusion::extension::adt_attribute_proxy<T, N, Const> >
353     {
354         static bool
callboost::spirit::traits::is_negative355         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
356         {
357             return test_negative(val.get());
358         }
359     };
360 
361     template <typename T, int N, bool Const>
362     struct is_zero<fusion::extension::adt_attribute_proxy<T, N, Const> >
363     {
364         static bool
callboost::spirit::traits::is_zero365         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
366         {
367             return test_zero(val.get());
368         }
369     };
370 
371     template <typename T, int N, bool Const>
372     struct is_nan<fusion::extension::adt_attribute_proxy<T, N, Const> >
373     {
374         static bool
callboost::spirit::traits::is_nan375         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
376         {
377             return test_nan(val.get());
378         }
379     };
380 
381     template <typename T, int N, bool Const>
382     struct is_infinite<fusion::extension::adt_attribute_proxy<T, N, Const> >
383     {
384         static bool
callboost::spirit::traits::is_infinite385         call(fusion::extension::adt_attribute_proxy<T, N, Const> const& val)
386         {
387             return test_infinite(val.get());
388         }
389     };
390 }}}
391 
392 ///////////////////////////////////////////////////////////////////////////////
393 namespace boost { namespace spirit { namespace result_of
394 {
395     template <typename T, int N, bool Const>
396     struct optional_value<fusion::extension::adt_attribute_proxy<T, N, Const> >
397       : result_of::optional_value<
398             typename remove_const<
399                 typename remove_reference<
400                     typename fusion::extension::adt_attribute_proxy<T, N, Const>::type
401                 >::type
402             >::type>
403     {};
404 }}}
405 
406 #endif
407