1 ///////////////////////////////////////////////////////////////////////////////
2 // cons.hpp
3 //
4 //  Copyright 2008 Eric Niebler. Distributed under the Boost
5 //  Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
9 #define BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
10 
11 #include <boost/version.hpp>
12 
13 #if BOOST_VERSION >= 103300
14 
15 // In Boost 1.33+, we have a cons list in Fusion, so just include it.
16 
17 # if BOOST_VERSION >= 103500
18 #  include <boost/fusion/include/cons.hpp> // Boost 1.35+ has Fusion2
19 # else
20 #  include <boost/spirit/fusion/sequence/cons.hpp> // Fusion1
21 # endif
22 
23 #else
24 
25 // For earlier versions of Boost, put the definition of cons here
26 # include <boost/call_traits.hpp>
27 # include <boost/mpl/if.hpp>
28 # include <boost/mpl/eval_if.hpp>
29 # include <boost/mpl/identity.hpp>
30 # include <boost/type_traits/is_const.hpp>
31 # include <boost/type_traits/add_const.hpp>
32 # include <boost/type_traits/add_reference.hpp>
33 # include <boost/spirit/fusion/detail/config.hpp>
34 # include <boost/spirit/fusion/detail/access.hpp>
35 # include <boost/spirit/fusion/iterator/next.hpp>
36 # include <boost/spirit/fusion/iterator/equal_to.hpp>
37 # include <boost/spirit/fusion/iterator/as_fusion_iterator.hpp>
38 # include <boost/spirit/fusion/iterator/detail/iterator_base.hpp>
39 # include <boost/spirit/fusion/sequence/begin.hpp>
40 # include <boost/spirit/fusion/sequence/end.hpp>
41 # include <boost/spirit/fusion/sequence/as_fusion_sequence.hpp>
42 # include <boost/spirit/fusion/sequence/detail/sequence_base.hpp>
43 
44 namespace boost { namespace fusion
45 {
46     struct nil;
47 
48     struct cons_tag;
49 
50     template <typename Car, typename Cdr>
51     struct cons;
52 
53     struct cons_iterator_tag;
54 
55     template <typename Cons>
56     struct cons_iterator;
57 
58     namespace cons_detail
59     {
60         template <typename Iterator>
61         struct deref_traits_impl
62         {
63             typedef typename Iterator::cons_type cons_type;
64             typedef typename cons_type::car_type value_type;
65 
66             typedef typename mpl::eval_if<
67                 is_const<cons_type>
68               , add_reference<typename add_const<value_type>::type>
69               , add_reference<value_type> >::type
70             type;
71 
72             static type
callboost::fusion::cons_detail::deref_traits_impl73             call(Iterator const& i)
74             {
75                 return detail::ref(i.cons.car);
76             }
77         };
78 
79         template <typename Iterator>
80         struct next_traits_impl
81         {
82             typedef typename Iterator::cons_type cons_type;
83             typedef typename cons_type::cdr_type cdr_type;
84 
85             typedef cons_iterator<
86                 typename mpl::eval_if<
87                     is_const<cons_type>
88                   , add_const<cdr_type>
89                   , mpl::identity<cdr_type>
90                 >::type>
91             type;
92 
93             static type
callboost::fusion::cons_detail::next_traits_impl94             call(Iterator const& i)
95             {
96                 return type(detail::ref(i.cons.cdr));
97             }
98         };
99 
100         template <typename Iterator>
101         struct value_traits_impl
102         {
103             typedef typename Iterator::cons_type cons_type;
104             typedef typename cons_type::car_type type;
105         };
106 
107         template <typename Cons>
108         struct begin_traits_impl
109         {
110             typedef cons_iterator<Cons> type;
111 
112             static type
callboost::fusion::cons_detail::begin_traits_impl113             call(Cons& t)
114             {
115                 return type(t);
116             }
117         };
118 
119         template <typename Cons>
120         struct end_traits_impl
121         {
122             typedef cons_iterator<
123                 typename mpl::if_<is_const<Cons>, nil const, nil>::type>
124             type;
125 
126             static type
callboost::fusion::cons_detail::end_traits_impl127             call(Cons& t)
128             {
129                 FUSION_RETURN_DEFAULT_CONSTRUCTED;
130             }
131         };
132     } // namespace cons_detail
133 
134     namespace meta
135     {
136         template <typename Tag>
137         struct deref_impl;
138 
139         template <>
140         struct deref_impl<cons_iterator_tag>
141         {
142             template <typename Iterator>
143             struct apply : cons_detail::deref_traits_impl<Iterator> {};
144         };
145 
146         template <typename Tag>
147         struct next_impl;
148 
149         template <>
150         struct next_impl<cons_iterator_tag>
151         {
152             template <typename Iterator>
153             struct apply : cons_detail::next_traits_impl<Iterator> {};
154         };
155 
156         template <typename Tag>
157         struct value_impl;
158 
159         template <>
160         struct value_impl<cons_iterator_tag>
161         {
162             template <typename Iterator>
163             struct apply : cons_detail::value_traits_impl<Iterator> {};
164         };
165 
166         template <typename Tag>
167         struct begin_impl;
168 
169         template <>
170         struct begin_impl<cons_tag>
171         {
172             template <typename Sequence>
173             struct apply : cons_detail::begin_traits_impl<Sequence>
174             {};
175         };
176 
177         template <typename Tag>
178         struct end_impl;
179 
180         template <>
181         struct end_impl<cons_tag>
182         {
183             template <typename Sequence>
184             struct apply : cons_detail::end_traits_impl<Sequence>
185             {};
186         };
187     } // namespace meta
188 
189     template <typename Cons = nil>
190     struct cons_iterator : iterator_base<cons_iterator<Cons> >
191     {
192         typedef cons_iterator_tag tag;
193         typedef Cons cons_type;
194 
cons_iteratorboost::fusion::cons_iterator195         explicit cons_iterator(cons_type& cons_)
196             : cons(cons_) {}
197 
198         cons_type& cons;
199     };
200 
201     template <>
202     struct cons_iterator<nil> : iterator_base<cons_iterator<nil> >
203     {
204         typedef cons_iterator_tag tag;
205         typedef nil cons_type;
cons_iteratorboost::fusion::cons_iterator206         cons_iterator() {}
cons_iteratorboost::fusion::cons_iterator207         explicit cons_iterator(nil const&) {}
208     };
209 
210     template <>
211     struct cons_iterator<nil const> : iterator_base<cons_iterator<nil const> >
212     {
213         typedef cons_iterator_tag tag;
214         typedef nil const cons_type;
cons_iteratorboost::fusion::cons_iterator215         cons_iterator() {}
cons_iteratorboost::fusion::cons_iterator216         explicit cons_iterator(nil const&) {}
217     };
218 
219     struct nil : sequence_base<nil>
220     {
221         typedef cons_tag tag;
222         typedef void_t car_type;
223         typedef void_t cdr_type;
224     };
225 
226     template <typename Car, typename Cdr = nil>
227     struct cons : sequence_base<cons<Car,Cdr> >
228     {
229         typedef cons_tag tag;
230         typedef typename call_traits<Car>::value_type car_type;
231         typedef Cdr cdr_type;
232 
consboost::fusion::cons233         cons()
234           : car(), cdr() {}
235 
consboost::fusion::cons236         explicit cons(
237             typename call_traits<Car>::param_type car_
238           , typename call_traits<Cdr>::param_type cdr_ = Cdr())
239           : car(car_), cdr(cdr_) {}
240 
241         car_type car;
242         cdr_type cdr;
243     };
244 
245     template <typename Car>
246     inline cons<Car>
make_cons(Car const & car)247     make_cons(Car const& car)
248     {
249         return cons<Car>(car);
250     }
251 
252     template <typename Car, typename Cdr>
253     inline cons<Car, Cdr>
make_cons(Car const & car,Cdr const & cdr)254     make_cons(Car const& car, Cdr const& cdr)
255     {
256         return cons<Car, Cdr>(car, cdr);
257     }
258 }} // namespace boost::fusion
259 
260 namespace boost { namespace mpl
261 {
262     template <typename Tag>
263     struct begin_impl;
264 
265     template <typename Tag>
266     struct end_impl;
267 
268     template <>
269     struct begin_impl<fusion::cons_tag>
270       : fusion::meta::begin_impl<fusion::cons_tag>
271     {
272     };
273 
274     template <>
275     struct end_impl<fusion::cons_tag>
276       : fusion::meta::end_impl<fusion::cons_tag>
277     {
278     };
279 
280 }} // namespace boost::mpl
281 
282 #endif
283 
284 // Before Boost v1.33.1, Fusion cons lists were not valid MPL sequences.
285 #if BOOST_VERSION < 103301
286 namespace boost { namespace mpl
287 {
288     template<typename Iterator>
289     struct next;
290 
291     template<typename Cons>
292     struct next<fusion::cons_iterator<Cons> >
293       : fusion::cons_detail::next_traits_impl<fusion::cons_iterator<Cons> >
294     {
295     };
296 
297     template<typename Iterator>
298     struct deref;
299 
300     template<typename Cons>
301     struct deref<fusion::cons_iterator<Cons> >
302       : fusion::cons_detail::value_traits_impl<fusion::cons_iterator<Cons> >
303     {
304     };
305 
306 }} // namespace boost::mpl
307 #endif
308 
309 #endif
310