Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // depends_on.hpp Chris@16: // Chris@16: // Copyright 2005 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005 Chris@16: #define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005 Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace accumulators Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // as_feature Chris@16: template Chris@16: struct as_feature Chris@16: { Chris@16: typedef Feature type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // weighted_feature Chris@16: template Chris@16: struct as_weighted_feature Chris@16: { Chris@16: typedef Feature type; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // feature_of Chris@16: template Chris@16: struct feature_of Chris@16: { Chris@16: typedef Feature type; Chris@16: }; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // feature_tag Chris@16: template Chris@16: struct feature_tag Chris@16: { Chris@16: typedef typename Accumulator::feature_tag type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct undroppable Chris@16: { Chris@16: typedef Feature type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct undroppable > Chris@16: { Chris@16: typedef Feature type; Chris@16: }; Chris@16: Chris@16: // For the purpose of determining whether one feature depends on another, Chris@16: // disregard whether the feature is droppable or not. Chris@16: template Chris@16: struct is_dependent_on Chris@16: : is_base_and_derived< Chris@16: typename feature_of::type>::type Chris@16: , typename undroppable::type Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct dependencies_of Chris@16: { Chris@16: typedef typename Feature::dependencies type; Chris@16: }; Chris@16: Chris@16: // Should use mpl::insert_range, but doesn't seem to work with mpl sets Chris@16: template Chris@16: struct set_insert_range Chris@16: : mpl::fold< Chris@16: Range Chris@16: , Set Chris@16: , mpl::insert Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct collect_abstract_features Chris@16: : mpl::fold< Chris@16: Features Chris@16: , mpl::set0<> Chris@16: , set_insert_range< Chris@16: mpl::insert > Chris@16: , collect_abstract_features > Chris@16: > Chris@16: > Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct depends_on_base Chris@16: : mpl::inherit_linearly< Chris@16: typename mpl::sort< Chris@16: typename mpl::copy< Chris@16: typename collect_abstract_features::type Chris@16: , mpl::back_inserter > Chris@16: >::type Chris@16: , is_dependent_on Chris@16: >::type Chris@16: // Don't inherit multiply from a feature Chris@16: , mpl::if_< Chris@16: is_dependent_on Chris@16: , mpl::_1 Chris@16: , mpl::inherit Chris@16: > Chris@16: >::type Chris@16: { Chris@16: }; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: /// depends_on Chris@16: template Chris@16: struct depends_on Chris@16: : detail::depends_on_base< Chris@16: typename mpl::transform< Chris@16: mpl::vector Chris@16: , as_feature Chris@16: >::type Chris@16: > Chris@16: { Chris@16: typedef mpl::false_ is_weight_accumulator; Chris@16: typedef Chris@16: typename mpl::transform< Chris@16: mpl::vector Chris@16: , as_feature Chris@16: >::type Chris@16: dependencies; Chris@16: }; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct matches_feature Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: : is_same< Chris@16: typename feature_of::type>::type Chris@16: , typename feature_of::type>::type>::type Chris@16: > Chris@16: {}; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct contains_feature_of Chris@16: { Chris@16: typedef Chris@16: mpl::transform_view > > Chris@16: features_list; Chris@16: Chris@16: typedef Chris@16: typename feature_of::type>::type Chris@16: the_feature; Chris@16: Chris@16: typedef Chris@16: typename mpl::contains::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: // This is to work around a bug in early versions of Fusion which caused Chris@16: // a compile error if contains_feature_of is used as a Chris@16: // predicate to fusion::find_if Chris@16: template Chris@16: struct contains_feature_of_ Chris@16: { Chris@16: template Chris@16: struct apply Chris@16: : contains_feature_of Chris@16: {}; Chris@16: }; Chris@16: Chris@16: template< Chris@16: typename First Chris@16: , typename Last Chris@16: , bool is_empty = fusion::result_of::equal_to::value Chris@16: > Chris@16: struct build_acc_list; Chris@16: Chris@16: template Chris@16: struct build_acc_list Chris@16: { Chris@101: typedef fusion::nil_ type; Chris@16: Chris@16: template Chris@101: static fusion::nil_ Chris@16: call(Args const &, First const&, Last const&) Chris@16: { Chris@101: return fusion::nil_(); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct build_acc_list Chris@16: { Chris@16: typedef Chris@16: build_acc_list::type, Last> Chris@16: next_build_acc_list; Chris@16: Chris@16: typedef fusion::cons< Chris@16: typename fusion::result_of::value_of::type Chris@16: , typename next_build_acc_list::type> Chris@16: type; Chris@16: Chris@16: template Chris@16: static type Chris@16: call(Args const &args, First const& f, Last const& l) Chris@16: { Chris@16: return type(args, next_build_acc_list::call(args, fusion::next(f), l)); Chris@16: } Chris@16: }; Chris@16: Chris@16: namespace meta Chris@16: { Chris@16: template Chris@16: struct make_acc_list Chris@16: : build_acc_list< Chris@16: typename fusion::result_of::begin::type Chris@16: , typename fusion::result_of::end::type Chris@16: > Chris@16: {}; Chris@16: } Chris@16: Chris@16: template Chris@16: typename meta::make_acc_list::type Chris@16: make_acc_list(Sequence const &seq, Args const &args) Chris@16: { Chris@16: return meta::make_acc_list::call(args, fusion::begin(seq), fusion::end(seq)); Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // checked_as_weighted_feature Chris@16: template Chris@16: struct checked_as_weighted_feature Chris@16: { Chris@16: typedef typename as_feature::type feature_type; Chris@16: typedef typename as_weighted_feature::type type; Chris@16: // weighted and non-weighted flavors should provide the same feature. Chris@16: BOOST_MPL_ASSERT(( Chris@16: is_same< Chris@16: typename feature_of::type Chris@16: , typename feature_of::type Chris@16: > Chris@16: )); Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // as_feature_list Chris@16: template Chris@16: struct as_feature_list Chris@16: : mpl::transform_view > Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@16: struct as_feature_list Chris@16: : mpl::transform_view > Chris@16: { Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // accumulator_wrapper Chris@16: template Chris@16: struct accumulator_wrapper Chris@16: : Accumulator Chris@16: { Chris@16: typedef Feature feature_tag; Chris@16: Chris@16: accumulator_wrapper(accumulator_wrapper const &that) Chris@16: : Accumulator(*static_cast(&that)) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: accumulator_wrapper(Args const &args) Chris@16: : Accumulator(args) Chris@16: { Chris@16: } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // to_accumulator Chris@16: template Chris@16: struct to_accumulator Chris@16: { Chris@16: typedef Chris@16: accumulator_wrapper< Chris@16: typename mpl::apply2::type Chris@16: , Feature Chris@16: > Chris@16: type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct to_accumulator > Chris@16: { Chris@16: BOOST_MPL_ASSERT((is_same)); Chris@16: BOOST_MPL_ASSERT((is_same)); Chris@16: Chris@16: typedef Chris@16: accumulator_wrapper< Chris@16: typename mpl::apply2::type Chris@16: , Feature Chris@16: > Chris@16: accumulator_type; Chris@16: Chris@16: typedef Chris@16: typename mpl::if_< Chris@16: typename Feature::is_weight_accumulator Chris@16: , accumulator_wrapper, Feature> Chris@16: , accumulator_type Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: // BUGBUG work around an MPL bug wrt map insertion Chris@16: template Chris@16: struct insert_feature Chris@16: : mpl::eval_if< Chris@16: mpl::has_key::type> Chris@16: , mpl::identity Chris@16: , mpl::insert::type, Feature> > Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@16: struct insert_dependencies Chris@16: : mpl::fold< Chris@16: as_feature_list Chris@16: , FeatureMap Chris@16: , insert_dependencies< Chris@16: insert_feature Chris@16: , mpl::_2 Chris@16: , Weight Chris@16: > Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@16: struct insert_sequence Chris@16: : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps Chris@16: as_feature_list Chris@16: , FeatureMap Chris@16: , insert_feature Chris@16: > Chris@16: { Chris@16: }; Chris@16: Chris@16: template Chris@16: struct make_accumulator_tuple Chris@16: { Chris@16: typedef Chris@16: typename mpl::fold< Chris@16: as_feature_list Chris@16: , mpl::map0<> Chris@16: , mpl::if_< Chris@16: mpl::is_sequence Chris@16: , insert_sequence Chris@16: , insert_feature Chris@16: > Chris@16: >::type Chris@16: feature_map; Chris@16: Chris@16: // for each element in the map, add its dependencies also Chris@16: typedef Chris@16: typename mpl::fold< Chris@16: feature_map Chris@16: , feature_map Chris@16: , insert_dependencies, Weight> Chris@16: >::type Chris@16: feature_map_with_dependencies; Chris@16: Chris@16: // turn the map into a vector so we can sort it Chris@16: typedef Chris@16: typename mpl::insert_range< Chris@16: mpl::vector<> Chris@16: , mpl::end >::type Chris@16: , mpl::transform_view > Chris@16: >::type Chris@16: feature_vector_with_dependencies; Chris@16: Chris@16: // sort the features according to which is derived from which Chris@16: typedef Chris@16: typename mpl::sort< Chris@16: feature_vector_with_dependencies Chris@16: , is_dependent_on Chris@16: >::type Chris@16: sorted_feature_vector; Chris@16: Chris@16: // From the vector of features, construct a vector of accumulators Chris@16: typedef Chris@16: typename mpl::transform< Chris@16: sorted_feature_vector Chris@16: , to_accumulator Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: }} // namespace boost::accumulators Chris@16: Chris@16: #endif