File indexing completed on 2024-11-15 09:02:20
0001
0002
0003
0004
0005
0006
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
0051 template<typename Feature>
0052 struct as_feature
0053 {
0054 typedef Feature type;
0055 };
0056
0057
0058
0059 template<typename Feature>
0060 struct as_weighted_feature
0061 {
0062 typedef Feature type;
0063 };
0064
0065
0066
0067 template<typename Feature>
0068 struct feature_of
0069 {
0070 typedef Feature type;
0071 };
0072
0073 namespace detail
0074 {
0075
0076
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
0096
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
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
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
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
0205
0206
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
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
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
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
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
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
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<
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
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
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
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
0449 typedef
0450 typename mpl::transform<
0451 sorted_feature_vector
0452 , to_accumulator<mpl::_1, Sample, Weight>
0453 >::type
0454 type;
0455 };
0456
0457 }
0458
0459 }}
0460
0461 #endif