1 /*=============================================================================
2 Copyright (c) 2001-2006 Joel de Guzman
3 Copyright (c) 2006 Dan Marsden
5 Distributed under the Boost Software License, Version 1.0. (See accompanying
6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #if !defined(BOOST_FUSION_FOLD_HPP_20070528_1253)
9 #define BOOST_FUSION_FOLD_HPP_20070528_1253
11 #include <boost/mpl/bool.hpp>
12 #include <boost/mpl/apply.hpp>
13 #include <boost/mpl/identity.hpp>
14 #include <boost/fusion/iterator/equal_to.hpp>
15 #include <boost/fusion/sequence/intrinsic/begin.hpp>
16 #include <boost/fusion/sequence/intrinsic/end.hpp>
17 #include <boost/fusion/iterator/deref.hpp>
18 #include <boost/fusion/iterator/value_of.hpp>
19 #include <boost/fusion/iterator/next.hpp>
20 #include <boost/fusion/iterator/distance.hpp>
21 #include <boost/utility/result_of.hpp>
23 #include <boost/type_traits/add_const.hpp>
24 #include <boost/type_traits/add_reference.hpp>
26 namespace boost
{ namespace fusion
{
29 template <typename Sequence
, typename State
, typename F
>
35 struct apply_fold_result
37 template <typename Value
, typename State
>
39 : boost::result_of
<F(Value
,State
)>
43 template <typename Iterator
, typename State
, typename F
>
46 typedef typename
result_of::deref
<Iterator
>::type dereferenced
;
47 typedef typename add_reference
<typename add_const
<State
>::type
>::type lvalue_state
;
48 typedef typename
boost::result_of
<F(dereferenced
, lvalue_state
)>::type type
;
51 template <typename First
, typename Last
, typename State
, typename F
>
54 template <typename First
, typename Last
, typename State
, typename F
>
55 struct next_result_of_fold
59 typename
result_of::next
<First
>::type
61 , typename fold_apply
<First
, State
, F
>::type
67 template <typename First
, typename Last
, typename State
, typename F
>
72 result_of::equal_to
<First
, Last
>
73 , mpl::identity
<State
>
74 , next_result_of_fold
<First
, Last
, State
, F
>
78 typedef typename
result::type type
;
81 template<typename I0
, typename State
, typename F
, int N
>
82 struct result_of_unrolled_fold
;
87 template<typename I0
, typename State
, typename F
>
88 static typename result_of_unrolled_fold
<I0
, State
, F
, N
>::type
89 call(I0
const& i0
, State
const& state
, F f
)
91 typedef typename
result_of::next
<I0
>::type I1
;
92 I1 i1
= fusion::next(i0
);
93 typedef typename
result_of::next
<I1
>::type I2
;
94 I2 i2
= fusion::next(i1
);
95 typedef typename
result_of::next
<I2
>::type I3
;
96 I3 i3
= fusion::next(i2
);
97 typedef typename
result_of::next
<I3
>::type I4
;
98 I4 i4
= fusion::next(i3
);
100 return unrolled_fold
<N
-4>::call(i4
, f(*i3
, f(*i2
, f(*i1
, f(*i0
, state
)))), f
);
105 struct unrolled_fold
<3>
107 template<typename I0
, typename State
, typename F
>
108 static typename result_of_unrolled_fold
<I0
, State
, F
, 3>::type
109 call(I0
const& i0
, State
const& state
, F f
)
111 typedef typename
result_of::next
<I0
>::type I1
;
112 I1 i1
= fusion::next(i0
);
113 typedef typename
result_of::next
<I1
>::type I2
;
114 I2 i2
= fusion::next(i1
);
115 return f(*i2
, f(*i1
, f(*i0
, state
)));
120 struct unrolled_fold
<2>
122 template<typename I0
, typename State
, typename F
>
123 static typename result_of_unrolled_fold
<I0
, State
, F
, 2>::type
124 call(I0
const& i0
, State
const& state
, F f
)
126 typedef typename
result_of::next
<I0
>::type I1
;
127 I1 i1
= fusion::next(i0
);
128 return f(*i1
, f(*i0
, state
));
133 struct unrolled_fold
<1>
135 template<typename I0
, typename State
, typename F
>
136 static typename result_of_unrolled_fold
<I0
, State
, F
, 1>::type
137 call(I0
const& i0
, State
const& state
, F f
)
139 return f(*i0
, state
);
144 struct unrolled_fold
<0>
146 template<typename I0
, typename State
, typename F
>
147 static State
call(I0
const&, State
const& state
, F
)
154 template <typename First
, typename Last
, typename State
, typename F
>
156 linear_fold(First
const&, Last
const&, State
const& state
, F
, mpl::true_
)
162 template <typename First
, typename Last
, typename State
, typename F
>
163 inline typename static_fold
<First
, Last
, State
, F
>::type
171 return detail::linear_fold(
176 , result_of::equal_to
<typename
result_of::next
<First
>::type
, Last
>()
180 template<typename I0
, typename State
, typename F
, int N
>
181 struct result_of_unrolled_fold
183 typedef typename
result_of::next
<I0
>::type I1
;
184 typedef typename
result_of::next
<I1
>::type I2
;
185 typedef typename
result_of::next
<I2
>::type I3
;
186 typedef typename
result_of::next
<I3
>::type I4
;
187 typedef typename fold_apply
<I0
, State
, F
>::type Rest1
;
188 typedef typename fold_apply
<I1
, Rest1
, F
>::type Rest2
;
189 typedef typename fold_apply
<I2
, Rest2
, F
>::type Rest3
;
190 typedef typename fold_apply
<I3
, Rest3
, F
>::type Rest4
;
192 typedef typename result_of_unrolled_fold
<I4
, Rest4
, F
, N
-4>::type type
;
195 template<typename I0
, typename State
, typename F
>
196 struct result_of_unrolled_fold
<I0
, State
, F
, 3>
198 typedef typename
result_of::next
<I0
>::type I1
;
199 typedef typename
result_of::next
<I1
>::type I2
;
200 typedef typename fold_apply
<I0
, State
, F
>::type Rest
;
201 typedef typename fold_apply
<I1
, Rest
, F
>::type Rest2
;
202 typedef typename fold_apply
<I2
, Rest2
, F
>::type type
;
205 template<typename I0
, typename State
, typename F
>
206 struct result_of_unrolled_fold
<I0
, State
, F
, 2>
208 typedef typename
result_of::next
<I0
>::type I1
;
209 typedef typename fold_apply
<I0
, State
, F
>::type Rest
;
210 typedef typename fold_apply
<I1
, Rest
, F
>::type type
;
213 template<typename I0
, typename State
, typename F
>
214 struct result_of_unrolled_fold
<I0
, State
, F
, 1>
216 typedef typename fold_apply
<I0
, State
, F
>::type type
;
219 template<typename I0
, typename State
, typename F
>
220 struct result_of_unrolled_fold
<I0
, State
, F
, 0>
225 template<typename Sequence
, typename State
, typename F
, bool>
228 template<typename Sequence
, typename State
, typename F
>
229 struct choose_fold
<Sequence
, State
, F
, true>
231 typedef typename
result_of::begin
<Sequence
>::type begin
;
232 typedef typename
result_of::end
<Sequence
>::type end
;
233 typedef typename result_of_unrolled_fold
<
234 begin
, State
, F
, result_of::distance
<begin
, end
>::type::value
>::type type
;
237 template<typename Sequence
, typename State
, typename F
>
238 struct choose_fold
<Sequence
, State
, F
, false>
242 typename
result_of::begin
<Sequence
>::type
243 , typename
result_of::end
<Sequence
>::type
250 template<typename Sequence
, typename State
, typename F
, typename Tag
>
251 typename
result_of::fold
<Sequence
, State
, F
>::type
252 fold(Sequence
& seq
, State
const& state
, F f
, Tag
)
259 , result_of::equal_to
<
260 typename
result_of::begin
<Sequence
>::type
261 , typename
result_of::end
<Sequence
>::type
>()
265 template<typename Sequence
, typename State
, typename F
>
266 typename
result_of::fold
<Sequence
, State
, F
>::type
267 fold(Sequence
& seq
, State
const& state
, F f
, random_access_traversal_tag
)
269 typedef typename
result_of::begin
<Sequence
>::type begin
;
270 typedef typename
result_of::end
<Sequence
>::type end
;
271 return unrolled_fold
<result_of::distance
<begin
, end
>::type::value
>::call(