/*============================================================================= Copyright (c) 2010 Christopher Schmidt Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #include <boost/config.hpp> #include <boost/detail/lightweight_test.hpp> #include <boost/fusion/sequence.hpp> #include <boost/fusion/iterator.hpp> #include <boost/fusion/algorithm/transformation/reverse.hpp> #include <boost/fusion/algorithm/iteration/fold.hpp> #include <boost/fusion/algorithm/iteration/reverse_fold.hpp> #include <boost/fusion/algorithm/iteration/iter_fold.hpp> #include <boost/fusion/algorithm/iteration/reverse_iter_fold.hpp> #include <boost/fusion/container/vector/convert.hpp> #include <boost/fusion/container/vector/vector.hpp> #include <boost/fusion/adapted/mpl.hpp> #include <boost/fusion/support/pair.hpp> #include <boost/fusion/mpl.hpp> #include <boost/mpl/transform.hpp> #include <boost/mpl/front.hpp> #include <boost/mpl/back.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/assert.hpp> #include <boost/mpl/for_each.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/back_inserter.hpp> #include <boost/mpl/always.hpp> #include <boost/mpl/copy.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/remove_reference.hpp> #include <iostream> namespace mpl=boost::mpl; namespace fusion=boost::fusion; #ifdef BOOST_FUSION_TEST_REVERSE_FOLD # ifdef BOOST_FUSION_TEST_ITER_FOLD # define BOOST_FUSION_TEST_FOLD_NAME reverse_iter_fold # else # define BOOST_FUSION_TEST_FOLD_NAME reverse_fold # endif #else # ifdef BOOST_FUSION_TEST_ITER_FOLD # define BOOST_FUSION_TEST_FOLD_NAME iter_fold # else # define BOOST_FUSION_TEST_FOLD_NAME fold # endif #endif struct sum { template<typename Sig> struct result; template<typename Self, typename State, typename T> struct result<Self(State,T)> : boost::fusion::result_of::make_pair< mpl::int_< boost::remove_reference< State >::type::first_type::value+1 > , int > { BOOST_MPL_ASSERT((typename boost::is_reference<State>::type)); BOOST_MPL_ASSERT((typename boost::is_reference<T>::type)); }; #ifdef BOOST_FUSION_TEST_ITER_FOLD template<typename State, typename It> typename result<sum const&(State const&,It const&)>::type operator()(State const& state, It const& it)const { static const int n=State::first_type::value; return fusion::make_pair<mpl::int_<n+1> >( state.second+fusion::deref(it)*n); } #else template<typename State> typename result<sum const&(State const&, int const&)>::type operator()(State const& state, int const& e)const { static const int n=State::first_type::value; return fusion::make_pair<mpl::int_<n+1> >(state.second+e*n); } #endif }; struct meta_sum { template<typename Sig> struct result; template<typename Self, typename State, typename T> struct result<Self(State,T)> { BOOST_MPL_ASSERT((typename boost::is_reference<State>::type)); BOOST_MPL_ASSERT((typename boost::is_reference<T>::type)); typedef typename boost::remove_reference<State>::type state; static const int n=mpl::front<state>::type::value; #ifdef BOOST_FUSION_TEST_ITER_FOLD typedef typename boost::fusion::result_of::value_of< typename boost::remove_reference<T>::type >::type t; #else typedef typename boost::remove_reference<T>::type t; #endif typedef mpl::vector< mpl::int_<n+1> , mpl::int_< mpl::back<state>::type::value+t::value*n > > type; }; template<typename State, typename T> typename result<meta_sum const&(State const&,T const&)>::type operator()(State const&, T const&)const; }; struct fold_test_n { template<typename I> void operator()(I)const { static const int n=I::value; typedef mpl::range_c<int, 0, n> range; static const int squares_sum=n*(n+1)*(2*n+1)/6; { mpl::range_c<int, 1, n+1> init_range; typename boost::fusion::result_of::as_vector< typename mpl::transform< range , mpl::always<int> , mpl::back_inserter<mpl::vector<> > >::type >::type vec( #ifdef BOOST_FUSION_TEST_REVERSE_FOLD fusion::reverse(init_range) #else init_range #endif ); int result=BOOST_FUSION_TEST_FOLD_NAME( vec, fusion::make_pair<mpl::int_<1> >(0), sum()).second; std::cout << n << ": " << result << std::endl; BOOST_TEST(result==squares_sum); } { typedef typename #ifdef BOOST_FUSION_TEST_REVERSE_FOLD boost::fusion::result_of::as_vector< typename mpl::copy< mpl::range_c<int, 1, n+1> , mpl::front_inserter<fusion::vector<> > >::type >::type #else boost::fusion::result_of::as_vector<mpl::range_c<int, 1, n+1> >::type #endif vec; typedef boost::is_same< typename boost::fusion::result_of::BOOST_FUSION_TEST_FOLD_NAME< vec , mpl::vector<mpl::int_<1>, mpl::int_<0> > , meta_sum >::type , typename mpl::if_c< !n , mpl::vector<mpl::int_<1>, mpl::int_<0> >& , mpl::vector<mpl::int_<n+1>, mpl::int_<squares_sum> > >::type > result_test; BOOST_MPL_ASSERT((result_test)); } } }; int main() { mpl::for_each<mpl::range_c<int, 0, 10> >(fold_test_n()); return boost::report_errors(); } #undef BOOST_FUSION_TEST_FOLD_NAME