1 /*=============================================================================
2 Copyright (c) 2010 Christopher Schmidt
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
8 #include <boost/config.hpp>
9 #include <boost/detail/lightweight_test.hpp>
10 #include <boost/fusion/sequence.hpp>
11 #include <boost/fusion/iterator.hpp>
12 #include <boost/fusion/algorithm/transformation/reverse.hpp>
13 #include <boost/fusion/algorithm/iteration/fold.hpp>
14 #include <boost/fusion/algorithm/iteration/reverse_fold.hpp>
15 #include <boost/fusion/algorithm/iteration/iter_fold.hpp>
16 #include <boost/fusion/algorithm/iteration/reverse_iter_fold.hpp>
17 #include <boost/fusion/container/vector/convert.hpp>
18 #include <boost/fusion/container/vector/vector.hpp>
19 #include <boost/fusion/adapted/mpl.hpp>
20 #include <boost/fusion/support/pair.hpp>
21 #include <boost/fusion/mpl.hpp>
22 #include <boost/mpl/transform.hpp>
23 #include <boost/mpl/front.hpp>
24 #include <boost/mpl/back.hpp>
25 #include <boost/mpl/int.hpp>
26 #include <boost/mpl/assert.hpp>
27 #include <boost/mpl/for_each.hpp>
28 #include <boost/mpl/range_c.hpp>
29 #include <boost/mpl/vector.hpp>
30 #include <boost/mpl/if.hpp>
31 #include <boost/mpl/back_inserter.hpp>
32 #include <boost/mpl/always.hpp>
33 #include <boost/mpl/copy.hpp>
34 #include <boost/type_traits/is_same.hpp>
35 #include <boost/type_traits/remove_reference.hpp>
36 #include <iostream>
37
38 namespace mpl=boost::mpl;
39 namespace fusion=boost::fusion;
40
41 #ifdef BOOST_FUSION_TEST_REVERSE_FOLD
42 # ifdef BOOST_FUSION_TEST_ITER_FOLD
43 # define BOOST_FUSION_TEST_FOLD_NAME reverse_iter_fold
44 # else
45 # define BOOST_FUSION_TEST_FOLD_NAME reverse_fold
46 # endif
47 #else
48 # ifdef BOOST_FUSION_TEST_ITER_FOLD
49 # define BOOST_FUSION_TEST_FOLD_NAME iter_fold
50 # else
51 # define BOOST_FUSION_TEST_FOLD_NAME fold
52 # endif
53 #endif
54
55 struct sum
56 {
57 template<typename Sig>
58 struct result;
59
60 template<typename Self, typename State, typename T>
61 struct result<Self(State,T)>
62 : boost::fusion::result_of::make_pair<
63 mpl::int_<
64 boost::remove_reference<
65 State
66 >::type::first_type::value+1
67 >
68 , int
69 >
70 {
71 BOOST_MPL_ASSERT((typename boost::is_reference<State>::type));
72 BOOST_MPL_ASSERT((typename boost::is_reference<T>::type));
73 };
74
75 #ifdef BOOST_FUSION_TEST_ITER_FOLD
76 template<typename State, typename It>
77 typename result<sum const&(State const&,It const&)>::type
operator ()sum78 operator()(State const& state, It const& it)const
79 {
80 static const int n=State::first_type::value;
81 return fusion::make_pair<mpl::int_<n+1> >(
82 state.second+fusion::deref(it)*n);
83 }
84 #else
85 template<typename State>
86 typename result<sum const&(State const&, int const&)>::type
operator ()sum87 operator()(State const& state, int const& e)const
88 {
89 static const int n=State::first_type::value;
90 return fusion::make_pair<mpl::int_<n+1> >(state.second+e*n);
91 }
92 #endif
93 };
94
95 struct meta_sum
96 {
97 template<typename Sig>
98 struct result;
99
100 template<typename Self, typename State, typename T>
101 struct result<Self(State,T)>
102 {
103 BOOST_MPL_ASSERT((typename boost::is_reference<State>::type));
104 BOOST_MPL_ASSERT((typename boost::is_reference<T>::type));
105
106 typedef typename boost::remove_reference<State>::type state;
107 static const int n=mpl::front<state>::type::value;
108
109 #ifdef BOOST_FUSION_TEST_ITER_FOLD
110 typedef typename
111 boost::fusion::result_of::value_of<
112 typename boost::remove_reference<T>::type
113 >::type
114 t;
115 #else
116 typedef typename boost::remove_reference<T>::type t;
117 #endif
118
119 typedef
120 mpl::vector<
121 mpl::int_<n+1>
122 , mpl::int_<
123 mpl::back<state>::type::value+t::value*n
124 >
125 >
126 type;
127 };
128
129 template<typename State, typename T>
130 typename result<meta_sum const&(State const&,T const&)>::type
131 operator()(State const&, T const&)const;
132 };
133
134 struct fold_test_n
135 {
136 template<typename I>
137 void
operator ()fold_test_n138 operator()(I)const
139 {
140 static const int n=I::value;
141 typedef mpl::range_c<int, 0, n> range;
142
143 static const int squares_sum=n*(n+1)*(2*n+1)/6;
144
145 {
146 mpl::range_c<int, 1, n+1> init_range;
147 typename boost::fusion::result_of::as_vector<
148 typename mpl::transform<
149 range
150 , mpl::always<int>
151 , mpl::back_inserter<mpl::vector<> >
152 >::type
153 >::type vec(
154 #ifdef BOOST_FUSION_TEST_REVERSE_FOLD
155 fusion::reverse(init_range)
156 #else
157 init_range
158 #endif
159 );
160
161 int result=BOOST_FUSION_TEST_FOLD_NAME(
162 vec,
163 fusion::make_pair<mpl::int_<1> >(0),
164 sum()).second;
165 std::cout << n << ": " << result << std::endl;
166 BOOST_TEST(result==squares_sum);
167 }
168
169 {
170 typedef typename
171 #ifdef BOOST_FUSION_TEST_REVERSE_FOLD
172 boost::fusion::result_of::as_vector<
173 typename mpl::copy<
174 mpl::range_c<int, 1, n+1>
175 , mpl::front_inserter<fusion::vector<> >
176 >::type
177 >::type
178 #else
179 boost::fusion::result_of::as_vector<mpl::range_c<int, 1, n+1> >::type
180 #endif
181 vec;
182
183 typedef
184 boost::is_same<
185 typename boost::fusion::result_of::BOOST_FUSION_TEST_FOLD_NAME<
186 vec
187 , mpl::vector<mpl::int_<1>, mpl::int_<0> >
188 , meta_sum
189 >::type
190 , typename mpl::if_c<
191 !n
192 , mpl::vector<mpl::int_<1>, mpl::int_<0> >&
193 , mpl::vector<mpl::int_<n+1>, mpl::int_<squares_sum> >
194 >::type
195 >
196 result_test;
197
198 BOOST_MPL_ASSERT((result_test));
199 }
200 }
201 };
202
203 int
main()204 main()
205 {
206 mpl::for_each<mpl::range_c<int, 0, 10> >(fold_test_n());
207
208 return boost::report_errors();
209 }
210
211 #undef BOOST_FUSION_TEST_FOLD_NAME
212
213