123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- ///////////////////////////////////////////////////////////////////////////////
- // 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/set.hpp>
- #include <boost/mpl/copy.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/back_inserter.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 feature_of<typename undroppable<B>::type>::type
- , typename undroppable<A>::type
- >
- {};
- template<typename Feature>
- struct dependencies_of
- {
- typedef typename Feature::dependencies type;
- };
- // Should use mpl::insert_range, but doesn't seem to work with mpl sets
- template<typename Set, typename Range>
- struct set_insert_range
- : mpl::fold<
- Range
- , Set
- , mpl::insert<mpl::_1, mpl::_2>
- >
- {};
- template<typename Features>
- struct collect_abstract_features
- : mpl::fold<
- Features
- , mpl::set0<>
- , set_insert_range<
- mpl::insert<mpl::_1, feature_of<mpl::_2> >
- , collect_abstract_features<dependencies_of<mpl::_2> >
- >
- >
- {};
- template<typename Features>
- struct depends_on_base
- : mpl::inherit_linearly<
- typename mpl::sort<
- typename mpl::copy<
- typename collect_abstract_features<Features>::type
- , mpl::back_inserter<mpl::vector0<> >
- >::type
- , 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 &seq, Args const &args)
- {
- return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));
- }
- 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 const>::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))
- {
- }
- accumulator_wrapper& operator=(accumulator_wrapper const &that)
- {
- *static_cast<Accumulator *>(this) = *static_cast<Accumulator const *>(&that);
- return *this;
- }
- 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 an 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
|