fold.hpp 6.3 KB

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