1 /*============================================================================= 2 Copyright (c) 2001-2011 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/support/config.hpp> 11 #include <boost/fusion/iterator/iterator_facade.hpp> 12 #include <boost/type_traits/is_const.hpp> 13 #include <boost/type_traits/add_const.hpp> 14 #include <boost/mpl/identity.hpp> 15 #include <boost/mpl/if.hpp> 16 #include <boost/mpl/eval_if.hpp> 17 #include <boost/mpl/or.hpp> 18 #include <boost/mpl/plus.hpp> 19 #include <boost/mpl/int.hpp> 20 #include <boost/mpl/apply.hpp> 21 #include <boost/tuple/tuple.hpp> 22 23 namespace boost { namespace fusion 24 { 25 struct forward_traversal_tag; 26 27 namespace detail 28 { 29 template <typename T> 30 struct boost_tuple_is_empty : mpl::false_ {}; 31 32 template <> 33 struct boost_tuple_is_empty<tuples::null_type> : mpl::true_ {}; 34 35 template <> 36 struct boost_tuple_is_empty<tuples::null_type const> : mpl::true_ {}; 37 38 template <> 39 struct boost_tuple_is_empty<tuples::tuple<> > : mpl::true_ {}; 40 41 template <> 42 struct boost_tuple_is_empty<tuples::tuple<> const> : mpl::true_ {}; 43 } 44 45 template <typename Cons> 46 struct boost_tuple_iterator_identity; 47 48 template <typename Cons = tuples::null_type> 49 struct boost_tuple_iterator 50 : iterator_facade<boost_tuple_iterator<Cons>, forward_traversal_tag> 51 { 52 typedef Cons cons_type; 53 54 typedef boost_tuple_iterator_identity< 55 typename add_const<Cons>::type> identity; 56 57 BOOST_FUSION_GPU_ENABLED boost_tuple_iteratorboost::fusion::boost_tuple_iterator58 explicit boost_tuple_iterator(Cons& in_cons) 59 : cons(in_cons) {} 60 Cons& cons; 61 62 template <typename Iterator> 63 struct value_of : mpl::identity<typename Iterator::cons_type::head_type> {}; 64 65 template <typename Iterator> 66 struct deref 67 { 68 typedef typename value_of<Iterator>::type element; 69 70 typedef typename 71 mpl::if_< 72 is_const<typename Iterator::cons_type> 73 , typename tuples::access_traits<element>::const_type 74 , typename tuples::access_traits<element>::non_const_type 75 >::type 76 type; 77 78 BOOST_FUSION_GPU_ENABLED 79 static type callboost::fusion::boost_tuple_iterator::deref80 call(Iterator const& iter) 81 { 82 return iter.cons.get_head(); 83 } 84 }; 85 86 template <typename Iterator> 87 struct next 88 { 89 typedef typename Iterator::cons_type cons_type; 90 typedef typename cons_type::tail_type tail_type; 91 92 typedef boost_tuple_iterator< 93 typename mpl::eval_if< 94 is_const<cons_type> 95 , add_const<tail_type> 96 , mpl::identity<tail_type> 97 >::type> 98 type; 99 100 BOOST_FUSION_GPU_ENABLED 101 static type callboost::fusion::boost_tuple_iterator::next102 call(Iterator const& iter) 103 { 104 return type(iter.cons.get_tail()); 105 } 106 }; 107 108 template <typename I1, typename I2> 109 struct distance; 110 111 // detail 112 template <typename I1, typename I2> 113 struct lazy_next_distance 114 { 115 typedef 116 typename mpl::plus< 117 mpl::int_<1>, 118 typename distance< 119 typename next<I1>::type, 120 I2 121 >::type 122 >::type type; 123 }; 124 125 template <typename I1, typename I2> 126 struct distance 127 { 128 typedef typename mpl::eval_if< 129 boost::is_same<I1, I2>, 130 mpl::int_<0>, 131 lazy_next_distance<I1, I2> 132 >::type type; 133 134 BOOST_FUSION_GPU_ENABLED 135 static type callboost::fusion::boost_tuple_iterator::distance136 call(I1 const&, I2 const&) 137 { 138 return type(); 139 } 140 }; 141 142 template <typename I1, typename I2> 143 struct equal_to 144 : is_same<typename I1::identity, typename I2::identity> 145 {}; 146 147 // silence MSVC warning C4512: assignment operator could not be generated 148 BOOST_DELETED_FUNCTION(boost_tuple_iterator& operator= (boost_tuple_iterator const&)) 149 }; 150 151 template <typename Null> 152 struct boost_tuple_null_iterator 153 : iterator_facade<boost_tuple_iterator<Null>, forward_traversal_tag> 154 { 155 typedef Null cons_type; 156 157 typedef boost_tuple_iterator_identity< 158 typename add_const<Null>::type> identity; 159 160 template <typename I1, typename I2> 161 struct equal_to 162 : mpl::or_< 163 is_same<I1, I2> 164 , mpl::and_< 165 detail::boost_tuple_is_empty<typename I1::cons_type> 166 , detail::boost_tuple_is_empty<typename I2::cons_type> 167 > 168 > 169 {}; 170 }; 171 172 template <> 173 struct boost_tuple_iterator<tuples::null_type> 174 : boost_tuple_null_iterator<tuples::null_type> 175 { 176 template <typename Cons> 177 BOOST_FUSION_GPU_ENABLED boost_tuple_iteratorboost::fusion::boost_tuple_iterator178 explicit boost_tuple_iterator(Cons const&) {} 179 }; 180 181 template <> 182 struct boost_tuple_iterator<tuples::null_type const> 183 : boost_tuple_null_iterator<tuples::null_type const> 184 { 185 template <typename Cons> 186 BOOST_FUSION_GPU_ENABLED boost_tuple_iteratorboost::fusion::boost_tuple_iterator187 explicit boost_tuple_iterator(Cons const&) {} 188 }; 189 190 template <> 191 struct boost_tuple_iterator<tuples::tuple<> > 192 : boost_tuple_null_iterator<tuples::tuple<> > 193 { 194 template <typename Cons> 195 BOOST_FUSION_GPU_ENABLED 196 explicit boost_tuple_iterator(Cons const&) {} 197 }; 198 199 template <> 200 struct boost_tuple_iterator<tuples::tuple<> const> 201 : boost_tuple_null_iterator<tuples::tuple<> const> 202 { 203 template <typename Cons> 204 BOOST_FUSION_GPU_ENABLED 205 explicit boost_tuple_iterator(Cons const&) {} 206 }; 207 }} 208 209 #ifdef BOOST_FUSION_WORKAROUND_FOR_LWG_2408 210 namespace std 211 { 212 template <typename Cons> 213 struct iterator_traits< ::boost::fusion::boost_tuple_iterator<Cons> > 214 { }; 215 } 216 #endif 217 218 #endif 219 220 221