1 ///////////////////////////////////////////////////////////////////////////////
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)
8 #ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
9 #define BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
11 #include <boost/version.hpp>
13 #if BOOST_VERSION >= 103300
15 // In Boost 1.33+, we have a cons list in Fusion, so just include it.
17 # if BOOST_VERSION >= 103500
18 # include <boost/fusion/include/cons.hpp> // Boost 1.35+ has Fusion2
20 # include <boost/spirit/fusion/sequence/cons.hpp> // Fusion1
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>
44 namespace boost { namespace fusion
50 template <typename Car, typename Cdr>
53 struct cons_iterator_tag;
55 template <typename Cons>
60 template <typename Iterator>
61 struct deref_traits_impl
63 typedef typename Iterator::cons_type cons_type;
64 typedef typename cons_type::car_type value_type;
66 typedef typename mpl::eval_if<
68 , add_reference<typename add_const<value_type>::type>
69 , add_reference<value_type> >::type
73 call(Iterator const& i)
75 return detail::ref(i.cons.car);
79 template <typename Iterator>
80 struct next_traits_impl
82 typedef typename Iterator::cons_type cons_type;
83 typedef typename cons_type::cdr_type cdr_type;
85 typedef cons_iterator<
86 typename mpl::eval_if<
89 , mpl::identity<cdr_type>
94 call(Iterator const& i)
96 return type(detail::ref(i.cons.cdr));
100 template <typename Iterator>
101 struct value_traits_impl
103 typedef typename Iterator::cons_type cons_type;
104 typedef typename cons_type::car_type type;
107 template <typename Cons>
108 struct begin_traits_impl
110 typedef cons_iterator<Cons> type;
119 template <typename Cons>
120 struct end_traits_impl
122 typedef cons_iterator<
123 typename mpl::if_<is_const<Cons>, nil const, nil>::type>
129 FUSION_RETURN_DEFAULT_CONSTRUCTED;
132 } // namespace cons_detail
136 template <typename Tag>
140 struct deref_impl<cons_iterator_tag>
142 template <typename Iterator>
143 struct apply : cons_detail::deref_traits_impl<Iterator> {};
146 template <typename Tag>
150 struct next_impl<cons_iterator_tag>
152 template <typename Iterator>
153 struct apply : cons_detail::next_traits_impl<Iterator> {};
156 template <typename Tag>
160 struct value_impl<cons_iterator_tag>
162 template <typename Iterator>
163 struct apply : cons_detail::value_traits_impl<Iterator> {};
166 template <typename Tag>
170 struct begin_impl<cons_tag>
172 template <typename Sequence>
173 struct apply : cons_detail::begin_traits_impl<Sequence>
177 template <typename Tag>
181 struct end_impl<cons_tag>
183 template <typename Sequence>
184 struct apply : cons_detail::end_traits_impl<Sequence>
189 template <typename Cons = nil>
190 struct cons_iterator : iterator_base<cons_iterator<Cons> >
192 typedef cons_iterator_tag tag;
193 typedef Cons cons_type;
195 explicit cons_iterator(cons_type& cons_)
202 struct cons_iterator<nil> : iterator_base<cons_iterator<nil> >
204 typedef cons_iterator_tag tag;
205 typedef nil cons_type;
207 explicit cons_iterator(nil const&) {}
211 struct cons_iterator<nil const> : iterator_base<cons_iterator<nil const> >
213 typedef cons_iterator_tag tag;
214 typedef nil const cons_type;
216 explicit cons_iterator(nil const&) {}
219 struct nil : sequence_base<nil>
221 typedef cons_tag tag;
222 typedef void_t car_type;
223 typedef void_t cdr_type;
226 template <typename Car, typename Cdr = nil>
227 struct cons : sequence_base<cons<Car,Cdr> >
229 typedef cons_tag tag;
230 typedef typename call_traits<Car>::value_type car_type;
231 typedef Cdr cdr_type;
237 typename call_traits<Car>::param_type car_
238 , typename call_traits<Cdr>::param_type cdr_ = Cdr())
239 : car(car_), cdr(cdr_) {}
245 template <typename Car>
247 make_cons(Car const& car)
249 return cons<Car>(car);
252 template <typename Car, typename Cdr>
253 inline cons<Car, Cdr>
254 make_cons(Car const& car, Cdr const& cdr)
256 return cons<Car, Cdr>(car, cdr);
258 }} // namespace boost::fusion
260 namespace boost { namespace mpl
262 template <typename Tag>
265 template <typename Tag>
269 struct begin_impl<fusion::cons_tag>
270 : fusion::meta::begin_impl<fusion::cons_tag>
275 struct end_impl<fusion::cons_tag>
276 : fusion::meta::end_impl<fusion::cons_tag>
280 }} // namespace boost::mpl
284 // Before Boost v1.33.1, Fusion cons lists were not valid MPL sequences.
285 #if BOOST_VERSION < 103301
286 namespace boost { namespace mpl
288 template<typename Iterator>
291 template<typename Cons>
292 struct next<fusion::cons_iterator<Cons> >
293 : fusion::cons_detail::next_traits_impl<fusion::cons_iterator<Cons> >
297 template<typename Iterator>
300 template<typename Cons>
301 struct deref<fusion::cons_iterator<Cons> >
302 : fusion::cons_detail::value_traits_impl<fusion::cons_iterator<Cons> >
306 }} // namespace boost::mpl