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_FOR_EACH_05052005_1028) 8 #define FUSION_FOR_EACH_05052005_1028 9 10 #include <boost/fusion/support/config.hpp> 11 #include <boost/fusion/sequence/intrinsic/begin.hpp> 12 #include <boost/fusion/sequence/intrinsic/end.hpp> 13 #include <boost/fusion/iterator/equal_to.hpp> 14 #include <boost/fusion/iterator/next.hpp> 15 #include <boost/fusion/iterator/deref.hpp> 16 #include <boost/fusion/iterator/distance.hpp> 17 #include <boost/fusion/support/category_of.hpp> 18 #include <boost/mpl/bool.hpp> 19 20 namespace boost { namespace fusion { 21 namespace detail 22 { 23 template <typename First, typename Last, typename F> 24 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED 25 inline void for_each_linear(First const &,Last const &,F const &,mpl::true_)26 for_each_linear(First const&, Last const&, F const&, mpl::true_) 27 { 28 } 29 30 template <typename First, typename Last, typename F> 31 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED 32 inline void for_each_linear(First const & first,Last const & last,F & f,mpl::false_)33 for_each_linear(First const& first, Last const& last, F& f, mpl::false_) 34 { 35 f(*first); 36 detail::for_each_linear(fusion::next(first), last, f, 37 result_of::equal_to<typename result_of::next<First>::type, Last>()); 38 } 39 40 41 template <typename Sequence, typename F, typename Tag> 42 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED 43 inline void for_each_dispatch(Sequence & seq,F & f,Tag)44 for_each_dispatch(Sequence& seq, F& f, Tag) 45 { 46 detail::for_each_linear( 47 fusion::begin(seq) 48 , fusion::end(seq) 49 , f 50 , result_of::equal_to< 51 typename result_of::begin<Sequence>::type 52 , typename result_of::end<Sequence>::type>()); 53 } 54 55 template<int N> 56 struct for_each_unrolled 57 { 58 template<typename I0, typename F> 59 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::for_each_unrolled60 static void call(I0 const& i0, F& f) 61 { 62 f(*i0); 63 typedef typename result_of::next<I0>::type I1; 64 I1 i1(fusion::next(i0)); 65 f(*i1); 66 typedef typename result_of::next<I1>::type I2; 67 I2 i2(fusion::next(i1)); 68 f(*i2); 69 typedef typename result_of::next<I2>::type I3; 70 I3 i3(fusion::next(i2)); 71 f(*i3); 72 for_each_unrolled<N-4>::call(fusion::next(i3), f); 73 } 74 }; 75 76 template<> 77 struct for_each_unrolled<3> 78 { 79 template<typename I0, typename F> 80 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::for_each_unrolled81 static void call(I0 const& i0, F& f) 82 { 83 f(*i0); 84 typedef typename result_of::next<I0>::type I1; 85 I1 i1(fusion::next(i0)); 86 f(*i1); 87 typedef typename result_of::next<I1>::type I2; 88 I2 i2(fusion::next(i1)); 89 f(*i2); 90 } 91 }; 92 93 template<> 94 struct for_each_unrolled<2> 95 { 96 template<typename I0, typename F> 97 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::for_each_unrolled98 static void call(I0 const& i0, F& f) 99 { 100 f(*i0); 101 typedef typename result_of::next<I0>::type I1; 102 I1 i1(fusion::next(i0)); 103 f(*i1); 104 } 105 }; 106 107 template<> 108 struct for_each_unrolled<1> 109 { 110 template<typename I0, typename F> 111 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::for_each_unrolled112 static void call(I0 const& i0, F& f) 113 { 114 f(*i0); 115 } 116 }; 117 118 template<> 119 struct for_each_unrolled<0> 120 { 121 template<typename It, typename F> 122 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED callboost::fusion::detail::for_each_unrolled123 static void call(It const&, F const&) 124 { 125 } 126 }; 127 128 template <typename Sequence, typename F> 129 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED 130 inline void for_each_dispatch(Sequence & seq,F & f,random_access_traversal_tag)131 for_each_dispatch(Sequence& seq, F& f, random_access_traversal_tag) 132 { 133 typedef typename result_of::begin<Sequence>::type begin; 134 typedef typename result_of::end<Sequence>::type end; 135 for_each_unrolled<result_of::distance<begin, end>::type::value>::call(fusion::begin(seq), f); 136 } 137 138 template <typename Sequence, typename F> 139 BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED 140 inline void for_each(Sequence & seq,F & f,mpl::false_)141 for_each(Sequence& seq, F& f, mpl::false_) // unsegmented implementation 142 { 143 detail::for_each_dispatch(seq, f, typename traits::category_of<Sequence>::type()); 144 } 145 }}} 146 147 148 #endif 149 150