accumulator_set.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 402 行

HPP
402
字号
///////////////////////////////////////////////////////////////////////////////// accumulator_set.hpp////  Copyright 2005 Eric Niebler. 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)#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005#include <boost/version.hpp>#include <boost/mpl/apply.hpp>#include <boost/mpl/assert.hpp>#include <boost/mpl/protect.hpp>#include <boost/mpl/identity.hpp>#include <boost/mpl/is_sequence.hpp>#include <boost/type_traits/is_same.hpp>#include <boost/type_traits/is_base_and_derived.hpp>#include <boost/parameter/parameters.hpp>#include <boost/preprocessor/repetition/repeat_from_to.hpp>#include <boost/preprocessor/repetition/enum_binary_params.hpp>#include <boost/accumulators/accumulators_fwd.hpp>#include <boost/accumulators/framework/depends_on.hpp>#include <boost/accumulators/framework/accumulator_concept.hpp>#include <boost/accumulators/framework/parameters/accumulator.hpp>#include <boost/accumulators/framework/parameters/sample.hpp>#include <boost/accumulators/framework/accumulators/external_accumulator.hpp>#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>#include <boost/fusion/include/any.hpp>#include <boost/fusion/include/find_if.hpp>#include <boost/fusion/include/for_each.hpp>#include <boost/fusion/include/filter_view.hpp>namespace boost { namespace accumulators{namespace detail{    ///////////////////////////////////////////////////////////////////////////////    // accumulator_visitor    //   wrap a boost::parameter argument pack in a Fusion extractor object    template<typename Args>    struct accumulator_visitor    {        explicit accumulator_visitor(Args const &args)          : args(args)        {        }        template<typename Accumulator>        void operator ()(Accumulator &accumulator) const        {            accumulator(this->args);        }    private:        accumulator_visitor &operator =(accumulator_visitor const &);        Args const &args;    };    template<typename Args>    inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args)    {        return accumulator_visitor<Args>(args);    }    typedef        parameter::parameters<            parameter::required<tag::accumulator>          , parameter::optional<tag::sample>          // ... and others which are not specified here...        >    accumulator_params;    ///////////////////////////////////////////////////////////////////////////////    // accumulator_set_base    struct accumulator_set_base    {    };    ///////////////////////////////////////////////////////////////////////////////    // is_accumulator_set    template<typename T>    struct is_accumulator_set      : is_base_and_derived<accumulator_set_base, T>    {    };} // namespace detail#ifdef _MSC_VER#pragma warning(push)#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list#endif////////////////////////////////////////////////////////////////////////////////// \brief A set of accumulators.////// accumulator_set resolves the dependencies between features and ensures that/// the accumulators in the set are updated in the proper order.////// acccumulator_set provides a general mechanism to visit the accumulators/// in the set in order, with or without a filter. You can also fetch a reference/// to an accumulator that corresponds to a feature.///template<typename Sample, typename Features, typename Weight>struct accumulator_set  : detail::accumulator_set_base{    typedef Sample sample_type;     ///< The type of the samples that will be accumulated    typedef Features features_type; ///< An MPL sequence of the features that should be accumulated.    typedef Weight weight_type;     ///< The type of the weight parameter. Must be a scalar. Defaults to void.    /// INTERNAL ONLY    ///    typedef        typename detail::make_accumulator_tuple<            Features          , Sample          , Weight        >::type    accumulators_mpl_vector;    // generate a fusion::list of accumulators    /// INTERNAL ONLY    ///    typedef        typename detail::meta::make_acc_list<            accumulators_mpl_vector        >::type    accumulators_type;    /// INTERNAL ONLY    ///    //BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>));    ///////////////////////////////////////////////////////////////////////////////    /// default-construct all contained accumulators    accumulator_set()      : accumulators(            detail::make_acc_list(                accumulators_mpl_vector()              , detail::accumulator_params()(*this)            )        )    {        // Add-ref the Features that the user has specified        this->template visit_if<detail::contains_feature_of_<Features> >(            detail::make_add_ref_visitor(detail::accumulator_params()(*this))        );    }    /// \overload    ///    /// \param a1 Optional named parameter to be passed to all the accumulators    template<typename A1>    explicit accumulator_set(A1 const &a1)      : accumulators(            detail::make_acc_list(                accumulators_mpl_vector()              , detail::accumulator_params()(*this, a1)            )        )    {        // Add-ref the Features that the user has specified        this->template visit_if<detail::contains_feature_of_<Features> >(            detail::make_add_ref_visitor(detail::accumulator_params()(*this))        );    }    // ... other overloads generated by Boost.Preprocessor:    /// INTERNAL ONLY    ///#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _)                                \    template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \    accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a))                   \      : accumulators(                                                                   \            detail::make_acc_list(                                                      \                accumulators_mpl_vector()                                               \              , detail::accumulator_params()(                                           \                    *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                      \                )                                                                       \            )                                                                           \        )                                                                               \    {                                                                                   \        /* Add-ref the Features that the user has specified */                          \        this->template visit_if<detail::contains_feature_of_<Features> >(               \            detail::make_add_ref_visitor(detail::accumulator_params()(*this))           \        );                                                                              \    }    /// INTERNAL ONLY    ///    BOOST_PP_REPEAT_FROM_TO(        2      , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)      , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR      , _    )    #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED    /// \overload    ///    template<typename A1, typename A2, ...>    accumulator_set(A1 const &a1, A2 const &a2, ...);    #endif    // ... other overloads generated by Boost.Preprocessor below ...    ///////////////////////////////////////////////////////////////////////////////    /// Visitation    /// \param func UnaryFunction which is invoked with each accumulator in turn.    template<typename UnaryFunction>    void visit(UnaryFunction const &func)    {        fusion::for_each(this->accumulators, func);    }    ///////////////////////////////////////////////////////////////////////////////    /// Conditional visitation    /// \param func UnaryFunction which is invoked with each accumulator in turn,    ///     provided the accumulator satisfies the MPL predicate FilterPred.    template<typename FilterPred, typename UnaryFunction>    void visit_if(UnaryFunction const &func)    {        fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators);        fusion::for_each(filtered_accs, func);    }        ///////////////////////////////////////////////////////////////////////////////    /// The return type of the operator() overloads is void.    typedef void result_type;    ///////////////////////////////////////////////////////////////////////////////    /// Accumulation    /// \param a1 Optional named parameter to be passed to all the accumulators    void operator ()()    {        this->visit(            detail::make_accumulator_visitor(                detail::accumulator_params()(*this)            )        );    }    template<typename A1>    void operator ()(A1 const &a1)    {        this->visit(            detail::make_accumulator_visitor(                detail::accumulator_params()(*this, a1)            )        );    }    // ... other overloads generated by Boost.Preprocessor:    /// INTERNAL ONLY    ///#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _)                              \    template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \    void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a))                  \    {                                                                                   \        this->visit(                                                                    \            detail::make_accumulator_visitor(                                           \                detail::accumulator_params()(                                           \                    *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                      \                )                                                                       \            )                                                                           \        );                                                                              \    }    /// INTERNAL ONLY    ///    BOOST_PP_REPEAT_FROM_TO(        2      , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)      , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP      , _    )    #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED    /// \overload    ///    template<typename A1, typename A2, ...>    void operator ()(A1 const &a1, A2 const &a2, ...);    #endif    ///////////////////////////////////////////////////////////////////////////////    /// Extraction    template<typename Feature>    struct apply      : fusion::result_of::value_of<            typename fusion::result_of::find_if<                accumulators_type              , detail::matches_feature<Feature>            >::type        >    {    };    ///////////////////////////////////////////////////////////////////////////////    /// Extraction    template<typename Feature>    typename apply<Feature>::type &extract()    {        return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);    }    /// \overload    template<typename Feature>    typename apply<Feature>::type const &extract() const    {        return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);    }    ///////////////////////////////////////////////////////////////////////////////    /// Drop    template<typename Feature>    void drop()    {        // You can only drop the features that you have specified explicitly        typedef typename apply<Feature>::type the_accumulator;        BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>));        typedef            typename feature_of<typename as_feature<Feature>::type>::type        the_feature;        (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))            .drop(detail::accumulator_params()(*this));        // Also drop accumulators that this feature depends on        typedef typename the_feature::dependencies dependencies;        this->template visit_if<detail::contains_feature_of_<dependencies> >(            detail::make_drop_visitor(detail::accumulator_params()(*this))        );    }private:    accumulators_type accumulators;};#ifdef _MSC_VER#pragma warning(pop)#endif///////////////////////////////////////////////////////////////////////////////// find_accumulator//   find an accumulator in an accumulator_set corresponding to a featuretemplate<typename Feature, typename AccumulatorSet>typename mpl::apply<AccumulatorSet, Feature>::type &find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet)){    return acc.template extract<Feature>();}/// \overloadtemplate<typename Feature, typename AccumulatorSet>typename mpl::apply<AccumulatorSet, Feature>::type const &find_accumulator(AccumulatorSet const &acc){    return acc.template extract<Feature>();}///////////////////////////////////////////////////////////////////////////////// extract_result//   extract a result from an accumulator set/// INTERNAL ONLY///#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _)                      \    template<                                                               \        typename Feature                                                    \      , typename AccumulatorSet                                             \        BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A)                   \    >                                                                       \    typename mpl::apply<AccumulatorSet, Feature>::type::result_type         \    extract_result(                                                         \        AccumulatorSet const &acc                                           \        BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a)           \    )                                                                       \    {                                                                       \        return find_accumulator<Feature>(acc).result(                       \            detail::accumulator_params()(                                   \                acc                                                         \                BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)                    \            )                                                               \        );                                                                  \    }BOOST_PP_REPEAT(    BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)  , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN  , _)}} // namespace boost::accumulators#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?