fold.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 279 行
HPP
279 行
/*============================================================================= Copyright (c) 2001-2006 Joel de Guzman Copyright (c) 2006 Dan Marsden 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)==============================================================================*/#if !defined(BOOST_FUSION_FOLD_HPP_20070528_1253)#define BOOST_FUSION_FOLD_HPP_20070528_1253#include <boost/mpl/bool.hpp>#include <boost/mpl/apply.hpp>#include <boost/mpl/identity.hpp>#include <boost/fusion/iterator/equal_to.hpp>#include <boost/fusion/sequence/intrinsic/begin.hpp>#include <boost/fusion/sequence/intrinsic/end.hpp>#include <boost/fusion/iterator/deref.hpp>#include <boost/fusion/iterator/value_of.hpp>#include <boost/fusion/iterator/next.hpp>#include <boost/fusion/iterator/distance.hpp>#include <boost/utility/result_of.hpp>#include <boost/type_traits/add_const.hpp>#include <boost/type_traits/add_reference.hpp>namespace boost { namespace fusion {namespace result_of{ template <typename Sequence, typename State, typename F> struct fold;}namespace detail{ template <typename F> struct apply_fold_result { template <typename Value, typename State> struct apply : boost::result_of<F(Value,State)> {}; }; template <typename Iterator, typename State, typename F> struct fold_apply { typedef typename result_of::deref<Iterator>::type dereferenced; typedef typename add_reference<typename add_const<State>::type>::type lvalue_state; typedef typename boost::result_of<F(dereferenced, lvalue_state)>::type type; }; template <typename First, typename Last, typename State, typename F> struct static_fold; template <typename First, typename Last, typename State, typename F> struct next_result_of_fold { typedef typename static_fold< typename result_of::next<First>::type , Last , typename fold_apply<First, State, F>::type , F >::type type; }; template <typename First, typename Last, typename State, typename F> struct static_fold { typedef typename mpl::if_< result_of::equal_to<First, Last> , mpl::identity<State> , next_result_of_fold<First, Last, State, F> >::type result; typedef typename result::type type; }; template<typename I0, typename State, typename F, int N> struct result_of_unrolled_fold; template<int N> struct unrolled_fold { template<typename I0, typename State, typename F> static typename result_of_unrolled_fold<I0, State, F, N>::type call(I0 const& i0, State const& state, F f) { typedef typename result_of::next<I0>::type I1; I1 i1 = fusion::next(i0); typedef typename result_of::next<I1>::type I2; I2 i2 = fusion::next(i1); typedef typename result_of::next<I2>::type I3; I3 i3 = fusion::next(i2); typedef typename result_of::next<I3>::type I4; I4 i4 = fusion::next(i3); return unrolled_fold<N-4>::call(i4, f(*i3, f(*i2, f(*i1, f(*i0, state)))), f); } }; template<> struct unrolled_fold<3> { template<typename I0, typename State, typename F> static typename result_of_unrolled_fold<I0, State, F, 3>::type call(I0 const& i0, State const& state, F f) { typedef typename result_of::next<I0>::type I1; I1 i1 = fusion::next(i0); typedef typename result_of::next<I1>::type I2; I2 i2 = fusion::next(i1); return f(*i2, f(*i1, f(*i0, state))); } }; template<> struct unrolled_fold<2> { template<typename I0, typename State, typename F> static typename result_of_unrolled_fold<I0, State, F, 2>::type call(I0 const& i0, State const& state, F f) { typedef typename result_of::next<I0>::type I1; I1 i1 = fusion::next(i0); return f(*i1, f(*i0, state)); } }; template<> struct unrolled_fold<1> { template<typename I0, typename State, typename F> static typename result_of_unrolled_fold<I0, State, F, 1>::type call(I0 const& i0, State const& state, F f) { return f(*i0, state); } }; template<> struct unrolled_fold<0> { template<typename I0, typename State, typename F> static State call(I0 const&, State const& state, F) { return state; } }; // terminal case template <typename First, typename Last, typename State, typename F> inline State const& linear_fold(First const&, Last const&, State const& state, F, mpl::true_) { return state; } // non-terminal case template <typename First, typename Last, typename State, typename F> inline typename static_fold<First, Last, State, F>::type linear_fold( First const& first , Last const& last , State const& state , F f , mpl::false_) { return detail::linear_fold( fusion::next(first) , last , f(*first, state) , f , result_of::equal_to<typename result_of::next<First>::type, Last>() ); } template<typename I0, typename State, typename F, int N> struct result_of_unrolled_fold { typedef typename result_of::next<I0>::type I1; typedef typename result_of::next<I1>::type I2; typedef typename result_of::next<I2>::type I3; typedef typename result_of::next<I3>::type I4; typedef typename fold_apply<I0, State, F>::type Rest1; typedef typename fold_apply<I1, Rest1, F>::type Rest2; typedef typename fold_apply<I2, Rest2, F>::type Rest3; typedef typename fold_apply<I3, Rest3, F>::type Rest4; typedef typename result_of_unrolled_fold<I4, Rest4, F, N-4>::type type; }; template<typename I0, typename State, typename F> struct result_of_unrolled_fold<I0, State, F, 3> { typedef typename result_of::next<I0>::type I1; typedef typename result_of::next<I1>::type I2; typedef typename fold_apply<I0, State, F>::type Rest; typedef typename fold_apply<I1, Rest, F>::type Rest2; typedef typename fold_apply<I2, Rest2, F>::type type; }; template<typename I0, typename State, typename F> struct result_of_unrolled_fold<I0, State, F, 2> { typedef typename result_of::next<I0>::type I1; typedef typename fold_apply<I0, State, F>::type Rest; typedef typename fold_apply<I1, Rest, F>::type type; }; template<typename I0, typename State, typename F> struct result_of_unrolled_fold<I0, State, F, 1> { typedef typename fold_apply<I0, State, F>::type type; }; template<typename I0, typename State, typename F> struct result_of_unrolled_fold<I0, State, F, 0> { typedef State type; }; template<typename Sequence, typename State, typename F, bool> struct choose_fold; template<typename Sequence, typename State, typename F> struct choose_fold<Sequence, State, F, true> { typedef typename result_of::begin<Sequence>::type begin; typedef typename result_of::end<Sequence>::type end; typedef typename result_of_unrolled_fold< begin, State, F, result_of::distance<begin, end>::type::value>::type type; }; template<typename Sequence, typename State, typename F> struct choose_fold<Sequence, State, F, false> { typedef typename detail::static_fold< typename result_of::begin<Sequence>::type , typename result_of::end<Sequence>::type , State , F >::type type; }; template<typename Sequence, typename State, typename F, typename Tag> typename result_of::fold<Sequence, State, F>::type fold(Sequence& seq, State const& state, F f, Tag) { return linear_fold( fusion::begin(seq) , fusion::end(seq) , state , f , result_of::equal_to< typename result_of::begin<Sequence>::type , typename result_of::end<Sequence>::type>() ); } template<typename Sequence, typename State, typename F> typename result_of::fold<Sequence, State, F>::type fold(Sequence& seq, State const& state, F f, random_access_traversal_tag) { typedef typename result_of::begin<Sequence>::type begin; typedef typename result_of::end<Sequence>::type end; return unrolled_fold<result_of::distance<begin, end>::type::value>::call( fusion::begin(seq) , state , f); }}}}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?