Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:02:20

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // depends_on.hpp
0003 //
0004 //  Copyright 2005 Eric Niebler. Distributed under the Boost
0005 //  Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005
0009 #define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005
0010 
0011 #include <boost/version.hpp>
0012 #include <boost/mpl/end.hpp>
0013 #include <boost/mpl/map.hpp>
0014 #include <boost/mpl/set.hpp>
0015 #include <boost/mpl/copy.hpp>
0016 #include <boost/mpl/fold.hpp>
0017 #include <boost/mpl/size.hpp>
0018 #include <boost/mpl/sort.hpp>
0019 #include <boost/mpl/insert.hpp>
0020 #include <boost/mpl/assert.hpp>
0021 #include <boost/mpl/remove.hpp>
0022 #include <boost/mpl/vector.hpp>
0023 #include <boost/mpl/inherit.hpp>
0024 #include <boost/mpl/identity.hpp>
0025 #include <boost/mpl/equal_to.hpp>
0026 #include <boost/mpl/contains.hpp>
0027 #include <boost/mpl/transform.hpp>
0028 #include <boost/mpl/is_sequence.hpp>
0029 #include <boost/mpl/placeholders.hpp>
0030 #include <boost/mpl/insert_range.hpp>
0031 #include <boost/mpl/back_inserter.hpp>
0032 #include <boost/mpl/transform_view.hpp>
0033 #include <boost/mpl/inherit_linearly.hpp>
0034 #include <boost/type_traits/is_base_and_derived.hpp>
0035 #include <boost/preprocessor/repetition/repeat.hpp>
0036 #include <boost/preprocessor/repetition/enum_params.hpp>
0037 #include <boost/preprocessor/facilities/intercept.hpp>
0038 #include <boost/accumulators/accumulators_fwd.hpp>
0039 #include <boost/fusion/include/next.hpp>
0040 #include <boost/fusion/include/equal_to.hpp>
0041 #include <boost/fusion/include/value_of.hpp>
0042 #include <boost/fusion/include/mpl.hpp>
0043 #include <boost/fusion/include/end.hpp>
0044 #include <boost/fusion/include/begin.hpp>
0045 #include <boost/fusion/include/cons.hpp>
0046 
0047 namespace boost { namespace accumulators
0048 {
0049     ///////////////////////////////////////////////////////////////////////////
0050     // as_feature
0051     template<typename Feature>
0052     struct as_feature
0053     {
0054         typedef Feature type;
0055     };
0056 
0057     ///////////////////////////////////////////////////////////////////////////
0058     // weighted_feature
0059     template<typename Feature>
0060     struct as_weighted_feature
0061     {
0062         typedef Feature type;
0063     };
0064 
0065     ///////////////////////////////////////////////////////////////////////////
0066     // feature_of
0067     template<typename Feature>
0068     struct feature_of
0069     {
0070         typedef Feature type;
0071     };
0072 
0073     namespace detail
0074     {
0075         ///////////////////////////////////////////////////////////////////////////
0076         // feature_tag
0077         template<typename Accumulator>
0078         struct feature_tag
0079         {
0080             typedef typename Accumulator::feature_tag type;
0081         };
0082 
0083         template<typename Feature>
0084         struct undroppable
0085         {
0086             typedef Feature type;
0087         };
0088 
0089         template<typename Feature>
0090         struct undroppable<tag::droppable<Feature> >
0091         {
0092             typedef Feature type;
0093         };
0094 
0095         // For the purpose of determining whether one feature depends on another,
0096         // disregard whether the feature is droppable or not.
0097         template<typename A, typename B>
0098         struct is_dependent_on
0099           : is_base_and_derived<
0100                 typename feature_of<typename undroppable<B>::type>::type
0101               , typename undroppable<A>::type
0102             >
0103         {};
0104 
0105         template<typename Feature>
0106         struct dependencies_of
0107         {
0108             typedef typename Feature::dependencies type;
0109         };
0110 
0111         // Should use mpl::insert_range, but doesn't seem to work with mpl sets
0112         template<typename Set, typename Range>
0113         struct set_insert_range
0114           : mpl::fold<
0115                 Range
0116               , Set
0117               , mpl::insert<mpl::_1, mpl::_2>
0118             >
0119         {};
0120 
0121         template<typename Features>
0122         struct collect_abstract_features
0123           : mpl::fold<
0124                 Features
0125               , mpl::set0<>
0126               , set_insert_range<
0127                     mpl::insert<mpl::_1, feature_of<mpl::_2> >
0128                   , collect_abstract_features<dependencies_of<mpl::_2> >
0129                 >
0130             >
0131         {};
0132 
0133         template<typename Features>
0134         struct depends_on_base
0135           : mpl::inherit_linearly<
0136                 typename mpl::sort<
0137                     typename mpl::copy<
0138                         typename collect_abstract_features<Features>::type
0139                       , mpl::back_inserter<mpl::vector0<> >
0140                     >::type
0141                   , is_dependent_on<mpl::_1, mpl::_2>
0142                 >::type
0143                 // Don't inherit multiply from a feature
0144               , mpl::if_<
0145                     is_dependent_on<mpl::_1, mpl::_2>
0146                   , mpl::_1
0147                   , mpl::inherit<mpl::_1, mpl::_2>
0148                 >
0149             >::type
0150         {
0151         };
0152     }
0153 
0154     ///////////////////////////////////////////////////////////////////////////
0155     /// depends_on
0156     template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)>
0157     struct depends_on
0158       : detail::depends_on_base<
0159             typename mpl::transform<
0160                 mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
0161               , as_feature<mpl::_1>
0162             >::type
0163         >
0164     {
0165         typedef mpl::false_ is_weight_accumulator;
0166         typedef
0167             typename mpl::transform<
0168                 mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
0169               , as_feature<mpl::_1>
0170             >::type
0171         dependencies;
0172     };
0173 
0174     namespace detail
0175     {
0176         template<typename Feature>
0177         struct matches_feature
0178         {
0179             template<typename Accumulator>
0180             struct apply
0181               : is_same<
0182                     typename feature_of<typename as_feature<Feature>::type>::type
0183                   , typename feature_of<typename as_feature<typename feature_tag<Accumulator>::type>::type>::type
0184                 >
0185             {};
0186         };
0187 
0188         template<typename Features, typename Accumulator>
0189         struct contains_feature_of
0190         {
0191             typedef
0192                 mpl::transform_view<Features, feature_of<as_feature<mpl::_> > >
0193             features_list;
0194 
0195             typedef
0196                 typename feature_of<typename feature_tag<Accumulator>::type>::type
0197             the_feature;
0198 
0199             typedef
0200                 typename mpl::contains<features_list, the_feature>::type
0201             type;
0202         };
0203 
0204         // This is to work around a bug in early versions of Fusion which caused
0205         // a compile error if contains_feature_of<List, mpl::_> is used as a
0206         // predicate to fusion::find_if
0207         template<typename Features>
0208         struct contains_feature_of_
0209         {
0210             template<typename Accumulator>
0211             struct apply
0212               : contains_feature_of<Features, Accumulator>
0213             {};
0214         };
0215 
0216         template<
0217             typename First
0218           , typename Last
0219           , bool is_empty = fusion::result_of::equal_to<First, Last>::value
0220         >
0221         struct build_acc_list;
0222 
0223         template<typename First, typename Last>
0224         struct build_acc_list<First, Last, true>
0225         {
0226             typedef fusion::nil_ type;
0227 
0228             template<typename Args>
0229             static fusion::nil_
0230             call(Args const &, First const&, Last const&)
0231             {
0232                 return fusion::nil_();
0233             }
0234         };
0235 
0236         template<typename First, typename Last>
0237         struct build_acc_list<First, Last, false>
0238         {
0239             typedef
0240                 build_acc_list<typename fusion::result_of::next<First>::type, Last>
0241             next_build_acc_list;
0242 
0243             typedef fusion::cons<
0244                 typename fusion::result_of::value_of<First>::type
0245               , typename next_build_acc_list::type>
0246             type;
0247 
0248             template<typename Args>
0249             static type
0250             call(Args const &args, First const& f, Last const& l)
0251             {
0252                 return type(args, next_build_acc_list::call(args, fusion::next(f), l));
0253             }
0254         };
0255 
0256         namespace meta
0257         {
0258             template<typename Sequence>
0259             struct make_acc_list
0260               : build_acc_list<
0261                     typename fusion::result_of::begin<Sequence>::type
0262                   , typename fusion::result_of::end<Sequence>::type
0263                 >
0264             {};
0265         }
0266 
0267         template<typename Sequence, typename Args>
0268         typename meta::make_acc_list<Sequence>::type
0269         make_acc_list(Sequence &seq, Args const &args)
0270         {
0271             return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));
0272         }
0273 
0274         template<typename Sequence, typename Args>
0275         typename meta::make_acc_list<Sequence>::type
0276         make_acc_list(Sequence const &seq, Args const &args)
0277         {
0278             return meta::make_acc_list<Sequence const>::call(args, fusion::begin(seq), fusion::end(seq));
0279         }
0280 
0281         ///////////////////////////////////////////////////////////////////////////
0282         // checked_as_weighted_feature
0283         template<typename Feature>
0284         struct checked_as_weighted_feature
0285         {
0286             typedef typename as_feature<Feature>::type feature_type;
0287             typedef typename as_weighted_feature<feature_type>::type type;
0288             // weighted and non-weighted flavors should provide the same feature.
0289             BOOST_MPL_ASSERT((
0290                 is_same<
0291                     typename feature_of<feature_type>::type
0292                   , typename feature_of<type>::type
0293                 >
0294             ));
0295         };
0296 
0297         ///////////////////////////////////////////////////////////////////////////
0298         // as_feature_list
0299         template<typename Features, typename Weight>
0300         struct as_feature_list
0301           : mpl::transform_view<Features, checked_as_weighted_feature<mpl::_1> >
0302         {
0303         };
0304 
0305         template<typename Features>
0306         struct as_feature_list<Features, void>
0307           : mpl::transform_view<Features, as_feature<mpl::_1> >
0308         {
0309         };
0310 
0311         ///////////////////////////////////////////////////////////////////////////
0312         // accumulator_wrapper
0313         template<typename Accumulator, typename Feature>
0314         struct accumulator_wrapper
0315           : Accumulator
0316         {
0317             typedef Feature feature_tag;
0318 
0319             accumulator_wrapper(accumulator_wrapper const &that)
0320               : Accumulator(*static_cast<Accumulator const *>(&that))
0321             {
0322             }
0323 
0324             accumulator_wrapper& operator=(accumulator_wrapper const &that)
0325             {
0326                 *static_cast<Accumulator *>(this) = *static_cast<Accumulator const *>(&that);
0327                 return *this;
0328             }
0329 
0330             template<typename Args>
0331             accumulator_wrapper(Args const &args)
0332               : Accumulator(args)
0333             {
0334             }
0335         };
0336 
0337         ///////////////////////////////////////////////////////////////////////////
0338         // to_accumulator
0339         template<typename Feature, typename Sample, typename Weight>
0340         struct to_accumulator
0341         {
0342             typedef
0343                 accumulator_wrapper<
0344                     typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
0345                   , Feature
0346                 >
0347             type;
0348         };
0349 
0350         template<typename Feature, typename Sample, typename Weight, typename Tag, typename AccumulatorSet>
0351         struct to_accumulator<Feature, Sample, tag::external<Weight, Tag, AccumulatorSet> >
0352         {
0353             BOOST_MPL_ASSERT((is_same<Tag, void>));
0354             BOOST_MPL_ASSERT((is_same<AccumulatorSet, void>));
0355 
0356             typedef
0357                 accumulator_wrapper<
0358                     typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
0359                   , Feature
0360                 >
0361             accumulator_type;
0362 
0363             typedef
0364                 typename mpl::if_<
0365                     typename Feature::is_weight_accumulator
0366                   , accumulator_wrapper<impl::external_impl<accumulator_type, tag::weights>, Feature>
0367                   , accumulator_type
0368                 >::type
0369             type;
0370         };
0371 
0372         // BUGBUG work around an MPL bug wrt map insertion
0373         template<typename FeatureMap, typename Feature>
0374         struct insert_feature
0375           : mpl::eval_if<
0376                 mpl::has_key<FeatureMap, typename feature_of<Feature>::type>
0377               , mpl::identity<FeatureMap>
0378               , mpl::insert<FeatureMap, mpl::pair<typename feature_of<Feature>::type, Feature> >
0379             >
0380         {
0381         };
0382 
0383         template<typename FeatureMap, typename Feature, typename Weight>
0384         struct insert_dependencies
0385           : mpl::fold<
0386                 as_feature_list<typename Feature::dependencies, Weight>
0387               , FeatureMap
0388               , insert_dependencies<
0389                     insert_feature<mpl::_1, mpl::_2>
0390                   , mpl::_2
0391                   , Weight
0392                 >
0393             >
0394         {
0395         };
0396 
0397         template<typename FeatureMap, typename Features, typename Weight>
0398         struct insert_sequence
0399           : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps
0400                 as_feature_list<Features, Weight>
0401               , FeatureMap
0402               , insert_feature<mpl::_1, mpl::_2>
0403             >
0404         {
0405         };
0406 
0407         template<typename Features, typename Sample, typename Weight>
0408         struct make_accumulator_tuple
0409         {
0410             typedef
0411                 typename mpl::fold<
0412                     as_feature_list<Features, Weight>
0413                   , mpl::map0<>
0414                   , mpl::if_<
0415                         mpl::is_sequence<mpl::_2>
0416                       , insert_sequence<mpl::_1, mpl::_2, Weight>
0417                       , insert_feature<mpl::_1, mpl::_2>
0418                     >
0419                 >::type
0420             feature_map;
0421 
0422             // for each element in the map, add its dependencies also
0423             typedef
0424                 typename mpl::fold<
0425                     feature_map
0426                   , feature_map
0427                   , insert_dependencies<mpl::_1, mpl::second<mpl::_2>, Weight>
0428                 >::type
0429             feature_map_with_dependencies;
0430 
0431             // turn the map into a vector so we can sort it
0432             typedef
0433                 typename mpl::insert_range<
0434                     mpl::vector<>
0435                   , mpl::end<mpl::vector<> >::type
0436                   , mpl::transform_view<feature_map_with_dependencies, mpl::second<mpl::_1> >
0437                 >::type
0438             feature_vector_with_dependencies;
0439 
0440             // sort the features according to which is derived from which
0441             typedef
0442                 typename mpl::sort<
0443                     feature_vector_with_dependencies
0444                   , is_dependent_on<mpl::_2, mpl::_1>
0445                 >::type
0446             sorted_feature_vector;
0447 
0448             // From the vector of features, construct a vector of accumulators
0449             typedef
0450                 typename mpl::transform<
0451                     sorted_feature_vector
0452                   , to_accumulator<mpl::_1, Sample, Weight>
0453                 >::type
0454             type;
0455         };
0456 
0457     } // namespace detail
0458 
0459 }} // namespace boost::accumulators
0460 
0461 #endif