1 /*=============================================================================
2     Copyright (c) 2001-2006 Joel de Guzman
3 
4     Distributed under the Boost Software License, Version 1.0. (See accompanying
5     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 ==============================================================================*/
7 #if !defined(FUSION_BOOST_TUPLE_ITERATOR_09262006_1851)
8 #define FUSION_BOOST_TUPLE_ITERATOR_09262006_1851
9 
10 #include <boost/fusion/iterator/iterator_facade.hpp>
11 #include <boost/type_traits/is_const.hpp>
12 #include <boost/type_traits/add_const.hpp>
13 #include <boost/mpl/identity.hpp>
14 #include <boost/mpl/if.hpp>
15 #include <boost/mpl/eval_if.hpp>
16 #include <boost/mpl/or.hpp>
17 #include <boost/mpl/plus.hpp>
18 #include <boost/mpl/int.hpp>
19 #include <boost/mpl/apply.hpp>
20 #include <boost/tuple/tuple.hpp>
21 
22 namespace boost { namespace fusion
23 {
24     struct forward_traversal_tag;
25 
26     namespace detail
27     {
28         template <typename T>
29         struct boost_tuple_is_empty : mpl::false_ {};
30 
31         template <>
32         struct boost_tuple_is_empty<tuples::null_type> : mpl::true_ {};
33 
34         template <>
35         struct boost_tuple_is_empty<tuples::null_type const> : mpl::true_ {};
36 
37         template <>
38         struct boost_tuple_is_empty<tuples::tuple<> > : mpl::true_ {};
39 
40         template <>
41         struct boost_tuple_is_empty<tuples::tuple<> const> : mpl::true_ {};
42     }
43 
44     template <typename Cons = tuples::null_type>
45     struct boost_tuple_iterator
46         : iterator_facade<boost_tuple_iterator<Cons>, forward_traversal_tag>
47     {
48         typedef Cons cons_type;
49 
boost_tuple_iteratorboost::fusion::boost_tuple_iterator50         explicit boost_tuple_iterator(Cons& in_cons)
51             : cons(in_cons) {}
52         Cons& cons;
53 
54         template <typename Iterator>
55         struct value_of : mpl::identity<typename Iterator::cons_type::head_type> {};
56 
57         template <typename Iterator>
58         struct deref
59         {
60             typedef typename value_of<Iterator>::type element;
61 
62             typedef typename
63                 mpl::if_<
64                     is_const<typename Iterator::cons_type>
65                   , typename tuples::access_traits<element>::const_type
66                   , typename tuples::access_traits<element>::non_const_type
67                 >::type
68             type;
69 
70             static type
callboost::fusion::boost_tuple_iterator::deref71             call(Iterator const& iter)
72             {
73                 return iter.cons.get_head();
74             }
75         };
76 
77         template <typename Iterator>
78         struct next
79         {
80             typedef typename Iterator::cons_type cons_type;
81             typedef typename cons_type::tail_type tail_type;
82 
83             typedef boost_tuple_iterator<
84                 typename mpl::eval_if<
85                     is_const<cons_type>
86                   , add_const<tail_type>
87                   , mpl::identity<tail_type>
88                 >::type>
89             type;
90 
91             static type
callboost::fusion::boost_tuple_iterator::next92             call(Iterator const& iter)
93             {
94                 return type(iter.cons.get_tail());
95             }
96         };
97 
98         template <typename I1, typename I2>
99         struct distance;
100 
101         // detail
102         template <typename I1, typename I2>
103         struct lazy_next_distance
104         {
105             typedef
106                 typename mpl::plus<
107                     mpl::int_<1>,
108                     typename distance<
109                         typename next<I1>::type,
110                         I2
111                     >::type
112                 >::type type;
113         };
114 
115         template <typename I1, typename I2>
116         struct distance
117         {
118             typedef typename mpl::eval_if<
119                 boost::is_same<I1, I2>,
120                 mpl::int_<0>,
121                 lazy_next_distance<I1, I2>
122             >::type type;
123 
124             static type
callboost::fusion::boost_tuple_iterator::distance125             call(I1 const&, I2 const&)
126             {
127                 return type();
128             }
129         };
130 
131     private:
132         // silence MSVC warning C4512: assignment operator could not be generated
133         boost_tuple_iterator& operator= (boost_tuple_iterator const&);
134     };
135 
136     template <typename Null>
137     struct boost_tuple_null_iterator
138         : iterator_facade<boost_tuple_iterator<Null>, forward_traversal_tag>
139     {
140         typedef Null cons_type;
141 
142         template <typename I1, typename I2>
143         struct equal_to
144             : mpl::or_<
145                 is_same<I1, I2>
146               , mpl::and_<
147                     detail::boost_tuple_is_empty<typename I1::cons_type>
148                   , detail::boost_tuple_is_empty<typename I2::cons_type>
149                 >
150             >
151         {};
152     };
153 
154     template <>
155     struct boost_tuple_iterator<tuples::null_type>
156         : boost_tuple_null_iterator<tuples::null_type>
157     {
158         template <typename Cons>
boost_tuple_iteratorboost::fusion::boost_tuple_iterator159         explicit boost_tuple_iterator(Cons const&) {}
160     };
161 
162     template <>
163     struct boost_tuple_iterator<tuples::null_type const>
164         : boost_tuple_null_iterator<tuples::null_type const>
165     {
166         template <typename Cons>
boost_tuple_iteratorboost::fusion::boost_tuple_iterator167         explicit boost_tuple_iterator(Cons const&) {}
168     };
169 
170     template <>
171     struct boost_tuple_iterator<tuples::tuple<> >
172         : boost_tuple_null_iterator<tuples::tuple<> >
173     {
174         template <typename Cons>
175         explicit boost_tuple_iterator(Cons const&) {}
176     };
177 
178     template <>
179     struct boost_tuple_iterator<tuples::tuple<> const>
180         : boost_tuple_null_iterator<tuples::tuple<> const>
181     {
182         template <typename Cons>
183         explicit boost_tuple_iterator(Cons const&) {}
184     };
185 }}
186 
187 #endif
188 
189 
190