depends_on.hpp

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

HPP
412
字号
///////////////////////////////////////////////////////////////////////////////// depends_on.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_DEPENDS_ON_HPP_EAN_28_10_2005#define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005#include <boost/version.hpp>#include <boost/mpl/end.hpp>#include <boost/mpl/map.hpp>#include <boost/mpl/fold.hpp>#include <boost/mpl/size.hpp>#include <boost/mpl/sort.hpp>#include <boost/mpl/insert.hpp>#include <boost/mpl/assert.hpp>#include <boost/mpl/remove.hpp>#include <boost/mpl/vector.hpp>#include <boost/mpl/inherit.hpp>#include <boost/mpl/identity.hpp>#include <boost/mpl/equal_to.hpp>#include <boost/mpl/contains.hpp>#include <boost/mpl/transform.hpp>#include <boost/mpl/is_sequence.hpp>#include <boost/mpl/placeholders.hpp>#include <boost/mpl/insert_range.hpp>#include <boost/mpl/transform_view.hpp>#include <boost/mpl/inherit_linearly.hpp>#include <boost/type_traits/is_base_and_derived.hpp>#include <boost/preprocessor/repetition/repeat.hpp>#include <boost/preprocessor/repetition/enum_params.hpp>#include <boost/preprocessor/facilities/intercept.hpp>#include <boost/accumulators/accumulators_fwd.hpp>#include <boost/fusion/include/next.hpp>#include <boost/fusion/include/equal_to.hpp>#include <boost/fusion/include/value_of.hpp>#include <boost/fusion/include/mpl.hpp>#include <boost/fusion/include/end.hpp>#include <boost/fusion/include/begin.hpp>#include <boost/fusion/include/cons.hpp>namespace boost { namespace accumulators{    ///////////////////////////////////////////////////////////////////////////    // as_feature    template<typename Feature>    struct as_feature    {        typedef Feature type;    };    ///////////////////////////////////////////////////////////////////////////    // weighted_feature    template<typename Feature>    struct as_weighted_feature    {        typedef Feature type;    };    ///////////////////////////////////////////////////////////////////////////    // feature_of    template<typename Feature>    struct feature_of    {        typedef Feature type;    };    namespace detail    {        ///////////////////////////////////////////////////////////////////////////        // feature_tag        template<typename Accumulator>        struct feature_tag        {            typedef typename Accumulator::feature_tag type;        };        template<typename Feature>        struct undroppable        {            typedef Feature type;        };        template<typename Feature>        struct undroppable<tag::droppable<Feature> >        {            typedef Feature type;        };        // For the purpose of determining whether one feature depends on another,        // disregard whether the feature is droppable or not.        template<typename A, typename B>        struct is_dependent_on          : is_base_and_derived<                typename undroppable<B>::type              , typename undroppable<A>::type            >        {};        template<typename Features>        struct depends_on_base          : mpl::inherit_linearly<                typename mpl::sort<Features, is_dependent_on<mpl::_1, mpl::_2> >::type                // Don't inherit multiply from a feature              , mpl::if_<                    is_dependent_on<mpl::_1, mpl::_2>                  , mpl::_1                  , mpl::inherit<mpl::_1, mpl::_2>                >            >::type        {        };    }    ///////////////////////////////////////////////////////////////////////////    /// depends_on    template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)>    struct depends_on      : detail::depends_on_base<            typename mpl::transform<                mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>              , as_feature<mpl::_1>            >::type        >    {        typedef mpl::false_ is_weight_accumulator;        typedef            typename mpl::transform<                mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>              , as_feature<mpl::_1>            >::type        dependencies;    };    namespace detail    {        template<typename Feature>        struct matches_feature        {            template<typename Accumulator>            struct apply              : is_same<                    typename feature_of<typename as_feature<Feature>::type>::type                  , typename feature_of<typename as_feature<typename feature_tag<Accumulator>::type>::type>::type                >            {};        };        template<typename Features, typename Accumulator>        struct contains_feature_of        {            typedef                mpl::transform_view<Features, feature_of<as_feature<mpl::_> > >            features_list;            typedef                typename feature_of<typename feature_tag<Accumulator>::type>::type            the_feature;            typedef                typename mpl::contains<features_list, the_feature>::type            type;        };        // This is to work around a bug in early versions of Fusion which caused        // a compile error if contains_feature_of<List, mpl::_> is used as a        // predicate to fusion::find_if        template<typename Features>        struct contains_feature_of_        {            template<typename Accumulator>            struct apply              : contains_feature_of<Features, Accumulator>            {};        };        template<            typename First          , typename Last          , bool is_empty = fusion::result_of::equal_to<First, Last>::value        >        struct build_acc_list;        template<typename First, typename Last>        struct build_acc_list<First, Last, true>        {            typedef fusion::nil type;            template<typename Args>            static fusion::nil            call(Args const &, First const&, Last const&)            {                return fusion::nil();            }        };        template<typename First, typename Last>        struct build_acc_list<First, Last, false>        {            typedef                build_acc_list<typename fusion::result_of::next<First>::type, Last>            next_build_acc_list;            typedef fusion::cons<                typename fusion::result_of::value_of<First>::type              , typename next_build_acc_list::type>            type;            template<typename Args>            static type            call(Args const &args, First const& f, Last const& l)            {                return type(args, next_build_acc_list::call(args, fusion::next(f), l));            }        };        namespace meta        {            template<typename Sequence>            struct make_acc_list              : build_acc_list<                    typename fusion::result_of::begin<Sequence>::type                  , typename fusion::result_of::end<Sequence>::type                >            {};        }        template<typename Sequence, typename Args>        typename meta::make_acc_list<Sequence>::type        make_acc_list(Sequence const &seq, Args const &args)        {            return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));        }        ///////////////////////////////////////////////////////////////////////////        // checked_as_weighted_feature        template<typename Feature>        struct checked_as_weighted_feature        {            typedef typename as_feature<Feature>::type feature_type;            typedef typename as_weighted_feature<feature_type>::type type;            // weighted and non-weighted flavors should provide the same feature.            BOOST_MPL_ASSERT((                is_same<                    typename feature_of<feature_type>::type                  , typename feature_of<type>::type                >            ));        };        ///////////////////////////////////////////////////////////////////////////        // as_feature_list        template<typename Features, typename Weight>        struct as_feature_list          : mpl::transform_view<Features, checked_as_weighted_feature<mpl::_1> >        {        };        template<typename Features>        struct as_feature_list<Features, void>          : mpl::transform_view<Features, as_feature<mpl::_1> >        {        };        ///////////////////////////////////////////////////////////////////////////        // accumulator_wrapper        template<typename Accumulator, typename Feature>        struct accumulator_wrapper          : Accumulator        {            typedef Feature feature_tag;            accumulator_wrapper(accumulator_wrapper const &that)              : Accumulator(*static_cast<Accumulator const *>(&that))            {            }            template<typename Args>            accumulator_wrapper(Args const &args)              : Accumulator(args)            {            }        };        ///////////////////////////////////////////////////////////////////////////        // to_accumulator        template<typename Feature, typename Sample, typename Weight>        struct to_accumulator        {            typedef                accumulator_wrapper<                    typename mpl::apply2<typename Feature::impl, Sample, Weight>::type                  , Feature                >            type;        };        template<typename Feature, typename Sample, typename Weight, typename Tag, typename AccumulatorSet>        struct to_accumulator<Feature, Sample, tag::external<Weight, Tag, AccumulatorSet> >        {            BOOST_MPL_ASSERT((is_same<Tag, void>));            BOOST_MPL_ASSERT((is_same<AccumulatorSet, void>));            typedef                accumulator_wrapper<                    typename mpl::apply2<typename Feature::impl, Sample, Weight>::type                  , Feature                >            accumulator_type;            typedef                typename mpl::if_<                    typename Feature::is_weight_accumulator                  , accumulator_wrapper<impl::external_impl<accumulator_type, tag::weights>, Feature>                  , accumulator_type                >::type            type;        };        // BUGBUG work around a MPL bug wrt map insertion        template<typename FeatureMap, typename Feature>        struct insert_feature          : mpl::eval_if<                mpl::has_key<FeatureMap, typename feature_of<Feature>::type>              , mpl::identity<FeatureMap>              , mpl::insert<FeatureMap, mpl::pair<typename feature_of<Feature>::type, Feature> >            >        {        };        template<typename FeatureMap, typename Feature, typename Weight>        struct insert_dependencies          : mpl::fold<                as_feature_list<typename Feature::dependencies, Weight>              , FeatureMap              , insert_dependencies<                    insert_feature<mpl::_1, mpl::_2>                  , mpl::_2                  , Weight                >            >        {        };        template<typename FeatureMap, typename Features, typename Weight>        struct insert_sequence          : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps                as_feature_list<Features, Weight>              , FeatureMap              , insert_feature<mpl::_1, mpl::_2>            >        {        };        template<typename Features, typename Sample, typename Weight>        struct make_accumulator_tuple        {            typedef                typename mpl::fold<                    as_feature_list<Features, Weight>                  , mpl::map0<>                  , mpl::if_<                        mpl::is_sequence<mpl::_2>                      , insert_sequence<mpl::_1, mpl::_2, Weight>                      , insert_feature<mpl::_1, mpl::_2>                    >                >::type            feature_map;            // for each element in the map, add its dependencies also            typedef                typename mpl::fold<                    feature_map                  , feature_map                  , insert_dependencies<mpl::_1, mpl::second<mpl::_2>, Weight>                >::type            feature_map_with_dependencies;            // turn the map into a vector so we can sort it            typedef                typename mpl::insert_range<                    mpl::vector<>                  , mpl::end<mpl::vector<> >::type                  , mpl::transform_view<feature_map_with_dependencies, mpl::second<mpl::_1> >                >::type            feature_vector_with_dependencies;            // sort the features according to which is derived from which            typedef                typename mpl::sort<                    feature_vector_with_dependencies                  , is_dependent_on<mpl::_2, mpl::_1>                >::type            sorted_feature_vector;            // From the vector of features, construct a vector of accumulators            typedef                typename mpl::transform<                    sorted_feature_vector                  , to_accumulator<mpl::_1, Sample, Weight>                >::type            type;        };    } // namespace detail}} // namespace boost::accumulators#endif

⌨️ 快捷键说明

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