1 /*============================================================================== 2 Copyright (c) 2013 Jamboree 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 #ifndef BOOST_FUSION_FLATTEN_VIEW_ITERATOR_HPP_INCLUDED 8 #define BOOST_FUSION_FLATTEN_VIEW_ITERATOR_HPP_INCLUDED 9 10 11 #include <boost/fusion/support/config.hpp> 12 #include <boost/mpl/bool.hpp> 13 #include <boost/mpl/eval_if.hpp> 14 #include <boost/type_traits/remove_reference.hpp> 15 #include <boost/fusion/container/list/cons.hpp> 16 #include <boost/fusion/support/unused.hpp> 17 #include <boost/fusion/include/equal_to.hpp> 18 #include <boost/fusion/iterator/next.hpp> 19 #include <boost/fusion/iterator/deref.hpp> 20 #include <boost/fusion/iterator/value_of.hpp> 21 22 23 namespace boost { namespace fusion 24 { 25 struct forward_traversal_tag; 26 struct flatten_view_iterator_tag; 27 28 template<class First, class Base> 29 struct flatten_view_iterator 30 : iterator_base<flatten_view_iterator<First, Base> > 31 { 32 typedef flatten_view_iterator_tag fusion_tag; 33 typedef forward_traversal_tag category; 34 35 typedef convert_iterator<First> first_converter; 36 typedef typename first_converter::type first_type; 37 typedef Base base_type; 38 39 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED flatten_view_iteratorboost::fusion::flatten_view_iterator40 flatten_view_iterator(First const& first, Base const& base) 41 : first(first), base(base) 42 {} 43 44 first_type first; 45 base_type base; 46 }; 47 }} 48 49 namespace boost { namespace fusion { namespace detail 50 { 51 template<class Iterator, class = void> 52 struct make_descent_cons 53 { 54 typedef cons<Iterator> type; 55 56 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED applyboost::fusion::detail::make_descent_cons57 static inline type apply(Iterator const& it) 58 { 59 return type(it); 60 } 61 }; 62 63 template<class Iterator> 64 struct make_descent_cons<Iterator, 65 typename enable_if<traits::is_sequence< 66 typename result_of::value_of<Iterator>::type> >::type> 67 { 68 // we use 'value_of' above for convenience, assuming the value won't be reference, 69 // while we must use the regular 'deref' here for const issues... 70 typedef typename 71 remove_reference<typename result_of::deref<Iterator>::type>::type 72 sub_sequence; 73 74 typedef typename 75 result_of::begin<sub_sequence>::type 76 sub_begin; 77 78 typedef cons<Iterator, typename make_descent_cons<sub_begin>::type> type; 79 80 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED applyboost::fusion::detail::make_descent_cons81 static inline type apply(Iterator const& it) 82 { 83 return type(it, make_descent_cons<sub_begin>::apply( 84 fusion::begin(*it))); 85 } 86 }; 87 88 template<class Cons, class Base> 89 struct build_flatten_view_iterator; 90 91 template<class Car, class Base> 92 struct build_flatten_view_iterator<cons<Car>, Base> 93 { 94 typedef flatten_view_iterator<Car, Base> type; 95 96 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED applyboost::fusion::detail::build_flatten_view_iterator97 static inline type apply(cons<Car> const& cons, Base const& base) 98 { 99 return type(cons.car, base); 100 } 101 }; 102 103 template<class Car, class Cdr, class Base> 104 struct build_flatten_view_iterator<cons<Car, Cdr>, Base> 105 { 106 typedef flatten_view_iterator<Car, Base> next_base; 107 typedef build_flatten_view_iterator<Cdr, next_base> next; 108 typedef typename next::type type; 109 110 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED applyboost::fusion::detail::build_flatten_view_iterator111 static inline type apply(cons<Car, Cdr> const& cons, Base const& base) 112 { 113 return next::apply(cons.cdr, next_base(cons.car, base)); 114 } 115 }; 116 117 template<class Base, class Iterator, class = void> 118 struct seek_descent 119 { 120 typedef make_descent_cons<Iterator> make_descent_cons_; 121 typedef typename make_descent_cons_::type cons_type; 122 typedef 123 build_flatten_view_iterator<cons_type, Base> 124 build_flatten_view_iterator_; 125 typedef typename build_flatten_view_iterator_::type type; 126 127 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED applyboost::fusion::detail::seek_descent128 static inline type apply(Base const& base, Iterator const& it) 129 { 130 return build_flatten_view_iterator_::apply( 131 make_descent_cons_::apply(it), base); 132 } 133 }; 134 135 template<class Base, class Iterator> 136 struct seek_descent<Base, Iterator, 137 typename enable_if< 138 result_of::equal_to<Iterator, typename result_of::end< 139 typename result_of::value_of<Base>::type>::type> >::type> 140 { 141 typedef typename result_of::next<Base>::type type; 142 143 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED applyboost::fusion::detail::seek_descent144 static inline type apply(Base const& base, Iterator const&) 145 { 146 return fusion::next(base); 147 } 148 }; 149 }}} 150 151 namespace boost { namespace fusion { namespace extension 152 { 153 template<> 154 struct next_impl<flatten_view_iterator_tag> 155 { 156 template<typename Iterator> 157 struct apply 158 { 159 typedef typename Iterator::first_type first_type; 160 typedef typename Iterator::base_type base_type; 161 typedef typename result_of::next<first_type>::type next_type; 162 163 typedef detail::seek_descent<base_type, next_type> seek_descent; 164 typedef typename seek_descent::type type; 165 166 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED 167 static inline callboost::fusion::extension::next_impl::apply168 type call(Iterator const& it) 169 { 170 return seek_descent::apply(it.base, fusion::next(it.first)); 171 } 172 }; 173 }; 174 175 template<> 176 struct deref_impl<flatten_view_iterator_tag> 177 { 178 template<typename Iterator> 179 struct apply 180 { 181 typedef typename 182 result_of::deref<typename Iterator::first_type>::type 183 type; 184 185 BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED 186 static inline callboost::fusion::extension::deref_impl::apply187 type call(Iterator const& it) 188 { 189 return *it.first; 190 } 191 }; 192 }; 193 194 template<> 195 struct value_of_impl<flatten_view_iterator_tag> 196 { 197 template<typename Iterator> 198 struct apply 199 { 200 typedef typename 201 result_of::value_of<typename Iterator::first_type>::type 202 type; 203 }; 204 }; 205 }}} 206 207 #ifdef BOOST_FUSION_WORKAROUND_FOR_LWG_2408 208 namespace std 209 { 210 template <typename First, typename Base> 211 struct iterator_traits< ::boost::fusion::flatten_view_iterator<First, Base> > 212 { }; 213 } 214 #endif 215 216 217 #endif 218 219