File indexing completed on 2025-01-18 09:28:18
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
0009 #define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
0010
0011 #include <boost/version.hpp>
0012 #include <boost/mpl/bool.hpp>
0013 #include <boost/mpl/if.hpp>
0014 #include <boost/mpl/apply.hpp>
0015 #include <boost/mpl/assert.hpp>
0016 #include <boost/mpl/protect.hpp>
0017 #include <boost/mpl/identity.hpp>
0018 #include <boost/mpl/is_sequence.hpp>
0019 #include <boost/type_traits/is_same.hpp>
0020 #include <boost/type_traits/is_base_of.hpp>
0021 #include <boost/type_traits/remove_const.hpp>
0022 #include <boost/type_traits/remove_reference.hpp>
0023 #include <boost/core/enable_if.hpp>
0024 #include <boost/parameter/is_argument_pack.hpp>
0025 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
0026 #include <boost/preprocessor/repetition/enum_params.hpp>
0027 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
0028 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
0029 #include <boost/accumulators/accumulators_fwd.hpp>
0030 #include <boost/accumulators/framework/depends_on.hpp>
0031 #include <boost/accumulators/framework/accumulator_concept.hpp>
0032 #include <boost/accumulators/framework/parameters/accumulator.hpp>
0033 #include <boost/accumulators/framework/parameters/sample.hpp>
0034 #include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
0035 #include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>
0036 #include <boost/fusion/include/any.hpp>
0037 #include <boost/fusion/include/find_if.hpp>
0038 #include <boost/fusion/include/for_each.hpp>
0039 #include <boost/fusion/include/filter_view.hpp>
0040
0041 namespace boost { namespace accumulators
0042 {
0043
0044 namespace detail
0045 {
0046
0047
0048
0049 template<typename Args>
0050 struct accumulator_visitor
0051 {
0052 explicit accumulator_visitor(Args const &a)
0053 : args(a)
0054 {
0055 }
0056
0057 accumulator_visitor(accumulator_visitor const &other)
0058 : args(other.args)
0059 {
0060 }
0061
0062 template<typename Accumulator>
0063 void operator ()(Accumulator &accumulator) const
0064 {
0065 accumulator(this->args);
0066 }
0067
0068 private:
0069 BOOST_DELETED_FUNCTION(accumulator_visitor &operator =(accumulator_visitor const &))
0070 Args const &args;
0071 };
0072
0073 template<typename Args>
0074 inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args)
0075 {
0076 return accumulator_visitor<Args>(args);
0077 }
0078
0079
0080
0081 struct accumulator_set_base
0082 {
0083 };
0084
0085
0086
0087 template<typename T>
0088 struct is_accumulator_set
0089 : mpl::if_<
0090 boost::is_base_of<
0091 accumulator_set_base
0092 , typename boost::remove_const<
0093 typename boost::remove_reference<T>::type
0094 >::type
0095 >
0096 , mpl::true_
0097 , mpl::false_
0098 >::type
0099 {
0100 };
0101
0102
0103 template<typename Archive>
0104 struct serialize_accumulator
0105 {
0106 serialize_accumulator(Archive & _ar, const unsigned int _file_version) :
0107 ar(_ar), file_version(_file_version)
0108 {}
0109
0110 template<typename Accumulator>
0111 void operator ()(Accumulator &accumulator)
0112 {
0113 accumulator.serialize(ar, file_version);
0114 }
0115
0116 private:
0117 Archive& ar;
0118 const unsigned int file_version;
0119 };
0120
0121 }
0122
0123 #ifdef _MSC_VER
0124 #pragma warning(push)
0125 #pragma warning(disable: 4355)
0126 #endif
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138 template<typename Sample, typename Features, typename Weight>
0139 struct accumulator_set
0140 : detail::accumulator_set_base
0141 {
0142 typedef Sample sample_type;
0143 typedef Features features_type;
0144 typedef Weight weight_type;
0145
0146
0147
0148 typedef
0149 typename detail::make_accumulator_tuple<
0150 Features
0151 , Sample
0152 , Weight
0153 >::type
0154 accumulators_mpl_vector;
0155
0156
0157
0158
0159 typedef
0160 typename detail::meta::make_acc_list<
0161 accumulators_mpl_vector
0162 >::type
0163 accumulators_type;
0164
0165
0166
0167
0168
0169
0170
0171 accumulator_set()
0172 : accumulators(
0173 detail::make_acc_list(
0174 accumulators_mpl_vector()
0175 , (boost::accumulators::accumulator = *this)
0176 )
0177 )
0178 {
0179
0180 this->template visit_if<detail::contains_feature_of_<Features> >(
0181 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
0182 );
0183 }
0184
0185
0186
0187
0188 template<typename A1>
0189 explicit accumulator_set(
0190 A1 const &a1
0191 , typename boost::enable_if<
0192 parameter::is_argument_pack<A1>
0193 , detail::_enabler
0194 >::type = detail::_enabler()
0195 ) : accumulators(
0196 detail::make_acc_list(
0197 accumulators_mpl_vector()
0198 , (boost::accumulators::accumulator = *this, a1)
0199 )
0200 )
0201 {
0202
0203 this->template visit_if<detail::contains_feature_of_<Features> >(
0204 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
0205 );
0206 }
0207
0208
0209
0210
0211 template<typename A1>
0212 explicit accumulator_set(
0213 A1 const &a1
0214 , typename boost::disable_if<
0215 parameter::is_argument_pack<A1>
0216 , detail::_enabler
0217 >::type = detail::_enabler()
0218 ) : accumulators(
0219 detail::make_acc_list(
0220 accumulators_mpl_vector()
0221 , (
0222 boost::accumulators::accumulator = *this
0223 , boost::accumulators::sample = a1
0224 )
0225 )
0226 )
0227 {
0228
0229 this->template visit_if<detail::contains_feature_of_<Features> >(
0230 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
0231 );
0232 }
0233
0234
0235
0236
0237
0238 #define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \
0239 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
0240 accumulator_set( \
0241 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
0242 , typename boost::enable_if< \
0243 parameter::is_argument_pack<A0> \
0244 , detail::_enabler \
0245 >::type = detail::_enabler() \
0246 ) : accumulators( \
0247 detail::make_acc_list( \
0248 accumulators_mpl_vector() \
0249 , ( \
0250 boost::accumulators::accumulator = *this \
0251 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
0252 ) \
0253 ) \
0254 ) \
0255 { \
0256 \
0257 this->template visit_if<detail::contains_feature_of_<Features> >( \
0258 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) \
0259 ); \
0260 } \
0261 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
0262 accumulator_set( \
0263 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
0264 , typename boost::disable_if< \
0265 parameter::is_argument_pack<A0> \
0266 , detail::_enabler \
0267 >::type = detail::_enabler() \
0268 ) : accumulators( \
0269 detail::make_acc_list( \
0270 accumulators_mpl_vector() \
0271 , ( \
0272 boost::accumulators::accumulator = *this \
0273 , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
0274 ) \
0275 ) \
0276 ) \
0277 { \
0278 \
0279 this->template visit_if<detail::contains_feature_of_<Features> >( \
0280 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) \
0281 ); \
0282 }
0283
0284
0285
0286 BOOST_PP_REPEAT_FROM_TO(
0287 2
0288 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
0289 , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR
0290 , _
0291 )
0292
0293 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
0294
0295
0296 template<typename A1, typename A2, ...>
0297 accumulator_set(A1 const &a1, A2 const &a2, ...);
0298 #endif
0299
0300
0301
0302
0303
0304
0305 template<typename UnaryFunction>
0306 void visit(UnaryFunction const &func)
0307 {
0308 fusion::for_each(this->accumulators, func);
0309 }
0310
0311
0312
0313
0314
0315 template<typename FilterPred, typename UnaryFunction>
0316 void visit_if(UnaryFunction const &func)
0317 {
0318 fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators);
0319 fusion::for_each(filtered_accs, func);
0320 }
0321
0322
0323
0324 typedef void result_type;
0325
0326
0327
0328
0329 void operator ()()
0330 {
0331 this->visit(
0332 detail::make_accumulator_visitor(
0333 boost::accumulators::accumulator = *this
0334 )
0335 );
0336 }
0337
0338
0339
0340
0341
0342 #define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \
0343 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
0344 void operator ()( \
0345 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
0346 , typename boost::enable_if< \
0347 parameter::is_argument_pack<A0> \
0348 , detail::_enabler \
0349 >::type = detail::_enabler() \
0350 ) \
0351 { \
0352 this->visit( \
0353 detail::make_accumulator_visitor( \
0354 ( \
0355 boost::accumulators::accumulator = *this \
0356 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
0357 ) \
0358 ) \
0359 ); \
0360 } \
0361 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
0362 void operator ()( \
0363 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
0364 , typename boost::disable_if< \
0365 parameter::is_argument_pack<A0> \
0366 , detail::_enabler \
0367 >::type = detail::_enabler() \
0368 ) \
0369 { \
0370 this->visit( \
0371 detail::make_accumulator_visitor( \
0372 ( \
0373 boost::accumulators::accumulator = *this \
0374 , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
0375 ) \
0376 ) \
0377 ); \
0378 }
0379
0380
0381
0382 BOOST_PP_REPEAT_FROM_TO(
0383 1
0384 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
0385 , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP
0386 , _
0387 )
0388
0389 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
0390
0391
0392 template<typename A1, typename A2, ...>
0393 void operator ()(A1 const &a1, A2 const &a2, ...);
0394 #endif
0395
0396
0397
0398 template<typename Feature>
0399 struct apply
0400 : fusion::result_of::value_of<
0401 typename fusion::result_of::find_if<
0402 accumulators_type
0403 , detail::matches_feature<Feature>
0404 >::type
0405 >
0406 {
0407 };
0408
0409
0410
0411 template<typename Feature>
0412 typename apply<Feature>::type &extract()
0413 {
0414 return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
0415 }
0416
0417
0418 template<typename Feature>
0419 typename apply<Feature>::type const &extract() const
0420 {
0421 return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
0422 }
0423
0424
0425
0426 template<typename Feature>
0427 void drop()
0428 {
0429
0430 typedef typename apply<Feature>::type the_accumulator;
0431 BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>));
0432
0433 typedef
0434 typename feature_of<typename as_feature<Feature>::type>::type
0435 the_feature;
0436
0437 (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))
0438 .drop(boost::accumulators::accumulator = *this);
0439
0440
0441 typedef typename the_feature::dependencies dependencies;
0442 this->template visit_if<detail::contains_feature_of_<dependencies> >(
0443 detail::make_drop_visitor(boost::accumulators::accumulator = *this)
0444 );
0445 }
0446
0447
0448 template<class Archive>
0449 void serialize(Archive & ar, const unsigned int file_version)
0450 {
0451 detail::serialize_accumulator<Archive> serializer(ar, file_version);
0452 fusion::for_each(this->accumulators, serializer);
0453 }
0454
0455 private:
0456
0457 accumulators_type accumulators;
0458 };
0459
0460 #ifdef _MSC_VER
0461 #pragma warning(pop)
0462 #endif
0463
0464
0465
0466
0467 template<typename Feature, typename AccumulatorSet>
0468 typename mpl::apply<AccumulatorSet, Feature>::type &
0469 find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet))
0470 {
0471 return acc.template extract<Feature>();
0472 }
0473
0474
0475 template<typename Feature, typename AccumulatorSet>
0476 typename mpl::apply<AccumulatorSet, Feature>::type const &
0477 find_accumulator(AccumulatorSet const &acc)
0478 {
0479 return acc.template extract<Feature>();
0480 }
0481
0482 template<typename Feature, typename AccumulatorSet>
0483 typename mpl::apply<AccumulatorSet, Feature>::type::result_type
0484 extract_result(AccumulatorSet const &acc)
0485 {
0486 return find_accumulator<Feature>(acc).result(
0487 boost::accumulators::accumulator = acc
0488 );
0489 }
0490
0491
0492
0493
0494
0495
0496 #define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _) \
0497 template< \
0498 typename Feature \
0499 , typename AccumulatorSet \
0500 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
0501 > \
0502 typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
0503 extract_result( \
0504 AccumulatorSet const &acc \
0505 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
0506 , typename boost::enable_if< \
0507 parameter::is_argument_pack<A0> \
0508 , detail::_enabler \
0509 >::type \
0510 ) \
0511 { \
0512 return find_accumulator<Feature>(acc).result( \
0513 ( \
0514 boost::accumulators::accumulator = acc \
0515 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
0516 ) \
0517 ); \
0518 } \
0519 template< \
0520 typename Feature \
0521 , typename AccumulatorSet \
0522 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
0523 > \
0524 typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
0525 extract_result( \
0526 AccumulatorSet const &acc \
0527 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
0528 , typename boost::disable_if< \
0529 parameter::is_argument_pack<A0> \
0530 , detail::_enabler \
0531 >::type \
0532 ) \
0533 { \
0534 return find_accumulator<Feature>(acc).result(( \
0535 boost::accumulators::accumulator = acc \
0536 , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
0537 )); \
0538 }
0539
0540 BOOST_PP_REPEAT_FROM_TO(
0541 1
0542 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
0543 , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN
0544 , _
0545 )
0546
0547 }}
0548
0549 #endif