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 + -
显示快捷键?