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 #if BOOST_VERSION < 103300
47     struct void_t;
48 #endif
49 
50     struct nil;
51 
52     struct cons_tag;
53 
54     template <typename Car, typename Cdr>
55     struct cons;
56 
57     struct cons_iterator_tag;
58 
59     template <typename Cons>
60     struct cons_iterator;
61 
62     namespace cons_detail
63     {
64         template <typename Iterator>
65         struct deref_traits_impl
66         {
67             typedef typename Iterator::cons_type cons_type;
68             typedef typename cons_type::car_type value_type;
69 
70             typedef typename mpl::eval_if<
71                 is_const<cons_type>
72               , add_reference<typename add_const<value_type>::type>
73               , add_reference<value_type> >::type
74             type;
75 
76             static type
callboost::fusion::cons_detail::deref_traits_impl77             call(Iterator const& i)
78             {
79                 return detail::ref(i.cons.car);
80             }
81         };
82 
83         template <typename Iterator>
84         struct next_traits_impl
85         {
86             typedef typename Iterator::cons_type cons_type;
87             typedef typename cons_type::cdr_type cdr_type;
88 
89             typedef cons_iterator<
90                 typename mpl::eval_if<
91                     is_const<cons_type>
92                   , add_const<cdr_type>
93                   , mpl::identity<cdr_type>
94                 >::type>
95             type;
96 
97             static type
callboost::fusion::cons_detail::next_traits_impl98             call(Iterator const& i)
99             {
100                 return type(detail::ref(i.cons.cdr));
101             }
102         };
103 
104         template <typename Iterator>
105         struct value_traits_impl
106         {
107             typedef typename Iterator::cons_type cons_type;
108             typedef typename cons_type::car_type type;
109         };
110 
111         template <typename Cons>
112         struct begin_traits_impl
113         {
114             typedef cons_iterator<Cons> type;
115 
116             static type
callboost::fusion::cons_detail::begin_traits_impl117             call(Cons& t)
118             {
119                 return type(t);
120             }
121         };
122 
123         template <typename Cons>
124         struct end_traits_impl
125         {
126             typedef cons_iterator<
127                 typename mpl::if_<is_const<Cons>, nil const, nil>::type>
128             type;
129 
130             static type
callboost::fusion::cons_detail::end_traits_impl131             call(Cons& t)
132             {
133                 FUSION_RETURN_DEFAULT_CONSTRUCTED;
134             }
135         };
136     } // namespace cons_detail
137 
138     namespace meta
139     {
140         template <typename Tag>
141         struct deref_impl;
142 
143         template <>
144         struct deref_impl<cons_iterator_tag>
145         {
146             template <typename Iterator>
147             struct apply : cons_detail::deref_traits_impl<Iterator> {};
148         };
149 
150         template <typename Tag>
151         struct next_impl;
152 
153         template <>
154         struct next_impl<cons_iterator_tag>
155         {
156             template <typename Iterator>
157             struct apply : cons_detail::next_traits_impl<Iterator> {};
158         };
159 
160         template <typename Tag>
161         struct value_impl;
162 
163         template <>
164         struct value_impl<cons_iterator_tag>
165         {
166             template <typename Iterator>
167             struct apply : cons_detail::value_traits_impl<Iterator> {};
168         };
169 
170         template <typename Tag>
171         struct begin_impl;
172 
173         template <>
174         struct begin_impl<cons_tag>
175         {
176             template <typename Sequence>
177             struct apply : cons_detail::begin_traits_impl<Sequence>
178             {};
179         };
180 
181         template <typename Tag>
182         struct end_impl;
183 
184         template <>
185         struct end_impl<cons_tag>
186         {
187             template <typename Sequence>
188             struct apply : cons_detail::end_traits_impl<Sequence>
189             {};
190         };
191     } // namespace meta
192 
193     template <typename Cons = nil>
194     struct cons_iterator : iterator_base<cons_iterator<Cons> >
195     {
196         typedef cons_iterator_tag tag;
197         typedef Cons cons_type;
198 
cons_iteratorboost::fusion::cons_iterator199         explicit cons_iterator(cons_type& cons_)
200             : cons(cons_) {}
201 
202         cons_type& cons;
203     };
204 
205     template <>
206     struct cons_iterator<nil> : iterator_base<cons_iterator<nil> >
207     {
208         typedef cons_iterator_tag tag;
209         typedef nil cons_type;
cons_iteratorboost::fusion::cons_iterator210         cons_iterator() {}
cons_iteratorboost::fusion::cons_iterator211         explicit cons_iterator(nil const&) {}
212     };
213 
214     template <>
215     struct cons_iterator<nil const> : iterator_base<cons_iterator<nil const> >
216     {
217         typedef cons_iterator_tag tag;
218         typedef nil const cons_type;
cons_iteratorboost::fusion::cons_iterator219         cons_iterator() {}
cons_iteratorboost::fusion::cons_iterator220         explicit cons_iterator(nil const&) {}
221     };
222 
223     struct nil : sequence_base<nil>
224     {
225         typedef cons_tag tag;
226         typedef void_t car_type;
227         typedef void_t cdr_type;
228     };
229 
230     template <typename Car, typename Cdr = nil>
231     struct cons : sequence_base<cons<Car,Cdr> >
232     {
233         typedef cons_tag tag;
234         typedef typename call_traits<Car>::value_type car_type;
235         typedef Cdr cdr_type;
236 
consboost::fusion::cons237         cons()
238           : car(), cdr() {}
239 
consboost::fusion::cons240         explicit cons(
241             typename call_traits<Car>::param_type car_
242           , typename call_traits<Cdr>::param_type cdr_ = Cdr())
243           : car(car_), cdr(cdr_) {}
244 
245         car_type car;
246         cdr_type cdr;
247     };
248 
249     template <typename Car>
250     inline cons<Car>
make_cons(Car const & car)251     make_cons(Car const& car)
252     {
253         return cons<Car>(car);
254     }
255 
256     template <typename Car, typename Cdr>
257     inline cons<Car, Cdr>
make_cons(Car const & car,Cdr const & cdr)258     make_cons(Car const& car, Cdr const& cdr)
259     {
260         return cons<Car, Cdr>(car, cdr);
261     }
262 }} // namespace boost::fusion
263 
264 namespace boost { namespace mpl
265 {
266     template <typename Tag>
267     struct begin_impl;
268 
269     template <typename Tag>
270     struct end_impl;
271 
272     template <>
273     struct begin_impl<fusion::cons_tag>
274       : fusion::meta::begin_impl<fusion::cons_tag>
275     {
276     };
277 
278     template <>
279     struct end_impl<fusion::cons_tag>
280       : fusion::meta::end_impl<fusion::cons_tag>
281     {
282     };
283 
284 }} // namespace boost::mpl
285 
286 #endif
287 
288 // Before Boost v1.33.1, Fusion cons lists were not valid MPL sequences.
289 #if BOOST_VERSION < 103301
290 namespace boost { namespace mpl
291 {
292     template<typename Iterator>
293     struct next;
294 
295     template<typename Cons>
296     struct next<fusion::cons_iterator<Cons> >
297       : fusion::cons_detail::next_traits_impl<fusion::cons_iterator<Cons> >
298     {
299     };
300 
301     template<typename Iterator>
302     struct deref;
303 
304     template<typename Cons>
305     struct deref<fusion::cons_iterator<Cons> >
306       : fusion::cons_detail::value_traits_impl<fusion::cons_iterator<Cons> >
307     {
308     };
309 
310 }} // namespace boost::mpl
311 #endif
312 
313 #endif
314