1///////////////////////////////////////////////////////////////////////////////
2// accumulator_set.hpp
3//
4// Copyright 2005 Eric Niebler. Distributed under the Boost
5// Software License, Version 1.0. (See accompanying file
6// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
9#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
10
11#include <boost/version.hpp>
12#include <boost/mpl/bool.hpp>
13#include <boost/mpl/if.hpp>
14#include <boost/mpl/apply.hpp>
15#include <boost/mpl/assert.hpp>
16#include <boost/mpl/protect.hpp>
17#include <boost/mpl/identity.hpp>
18#include <boost/mpl/is_sequence.hpp>
19#include <boost/type_traits/is_same.hpp>
20#include <boost/type_traits/is_base_of.hpp>
21#include <boost/type_traits/remove_const.hpp>
22#include <boost/type_traits/remove_reference.hpp>
23#include <boost/core/enable_if.hpp>
24#include <boost/parameter/is_argument_pack.hpp>
25#include <boost/preprocessor/repetition/repeat_from_to.hpp>
26#include <boost/preprocessor/repetition/enum_params.hpp>
27#include <boost/preprocessor/repetition/enum_binary_params.hpp>
28#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
29#include <boost/accumulators/accumulators_fwd.hpp>
30#include <boost/accumulators/framework/depends_on.hpp>
31#include <boost/accumulators/framework/accumulator_concept.hpp>
32#include <boost/accumulators/framework/parameters/accumulator.hpp>
33#include <boost/accumulators/framework/parameters/sample.hpp>
34#include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
35#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>
36#include <boost/fusion/include/any.hpp>
37#include <boost/fusion/include/find_if.hpp>
38#include <boost/fusion/include/for_each.hpp>
39#include <boost/fusion/include/filter_view.hpp>
40
41namespace boost { namespace accumulators
42{
43
44namespace detail
45{
46 ///////////////////////////////////////////////////////////////////////////////
47 // accumulator_visitor
48 // wrap a boost::parameter argument pack in a Fusion extractor object
49 template<typename Args>
50 struct accumulator_visitor
51 {
52 explicit accumulator_visitor(Args const &a)
53 : args(a)
54 {
55 }
56
57 accumulator_visitor(accumulator_visitor const &other)
58 : args(other.args)
59 {
60 }
61
62 template<typename Accumulator>
63 void operator ()(Accumulator &accumulator) const
64 {
65 accumulator(this->args);
66 }
67
68 private:
69 BOOST_DELETED_FUNCTION(accumulator_visitor &operator =(accumulator_visitor const &))
70 Args const &args;
71 };
72
73 template<typename Args>
74 inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args)
75 {
76 return accumulator_visitor<Args>(args);
77 }
78
79 ///////////////////////////////////////////////////////////////////////////////
80 // accumulator_set_base
81 struct accumulator_set_base
82 {
83 };
84
85 ///////////////////////////////////////////////////////////////////////////////
86 // is_accumulator_set
87 template<typename T>
88 struct is_accumulator_set
89 : mpl::if_<
90 boost::is_base_of<
91 accumulator_set_base
92 , typename boost::remove_const<
93 typename boost::remove_reference<T>::type
94 >::type
95 >
96 , mpl::true_
97 , mpl::false_
98 >::type
99 {
100 };
101
102 // function object that serialize an accumulator
103 template<typename Archive>
104 struct serialize_accumulator
105 {
106 serialize_accumulator(Archive & _ar, const unsigned int _file_version) :
107 ar(_ar), file_version(_file_version)
108 {}
109
110 template<typename Accumulator>
111 void operator ()(Accumulator &accumulator)
112 {
113 accumulator.serialize(ar, file_version);
114 }
115
116 private:
117 Archive& ar;
118 const unsigned int file_version;
119 };
120
121} // namespace detail
122
123#ifdef _MSC_VER
124#pragma warning(push)
125#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
126#endif
127
128///////////////////////////////////////////////////////////////////////////////
129/// \brief A set of accumulators.
130///
131/// accumulator_set resolves the dependencies between features and ensures that
132/// the accumulators in the set are updated in the proper order.
133///
134/// acccumulator_set provides a general mechanism to visit the accumulators
135/// in the set in order, with or without a filter. You can also fetch a reference
136/// to an accumulator that corresponds to a feature.
137///
138template<typename Sample, typename Features, typename Weight>
139struct accumulator_set
140 : detail::accumulator_set_base
141{
142 typedef Sample sample_type; ///< The type of the samples that will be accumulated
143 typedef Features features_type; ///< An MPL sequence of the features that should be accumulated.
144 typedef Weight weight_type; ///< The type of the weight parameter. Must be a scalar. Defaults to void.
145
146 /// INTERNAL ONLY
147 ///
148 typedef
149 typename detail::make_accumulator_tuple<
150 Features
151 , Sample
152 , Weight
153 >::type
154 accumulators_mpl_vector;
155
156 // generate a fusion::list of accumulators
157 /// INTERNAL ONLY
158 ///
159 typedef
160 typename detail::meta::make_acc_list<
161 accumulators_mpl_vector
162 >::type
163 accumulators_type;
164
165 /// INTERNAL ONLY
166 ///
167 //BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>));
168
169 ///////////////////////////////////////////////////////////////////////////////
170 /// default-construct all contained accumulators
171 accumulator_set()
172 : accumulators(
173 detail::make_acc_list(
174 accumulators_mpl_vector()
175 , (boost::accumulators::accumulator = *this)
176 )
177 )
178 {
179 // Add-ref the Features that the user has specified
180 this->template visit_if<detail::contains_feature_of_<Features> >(
181 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
182 );
183 }
184
185 /// \overload
186 ///
187 /// \param a1 Optional named parameter to be passed to all the accumulators
188 template<typename A1>
189 explicit accumulator_set(
190 A1 const &a1
191 , typename boost::enable_if<
192 parameter::is_argument_pack<A1>
193 , detail::_enabler
194 >::type = detail::_enabler()
195 ) : accumulators(
196 detail::make_acc_list(
197 accumulators_mpl_vector()
198 , (boost::accumulators::accumulator = *this, a1)
199 )
200 )
201 {
202 // Add-ref the Features that the user has specified
203 this->template visit_if<detail::contains_feature_of_<Features> >(
204 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
205 );
206 }
207
208 /// \overload
209 ///
210 /// \param a1 Optional sample parameter to be passed to all the accumulators
211 template<typename A1>
212 explicit accumulator_set(
213 A1 const &a1
214 , typename boost::disable_if<
215 parameter::is_argument_pack<A1>
216 , detail::_enabler
217 >::type = detail::_enabler()
218 ) : accumulators(
219 detail::make_acc_list(
220 accumulators_mpl_vector()
221 , (
222 boost::accumulators::accumulator = *this
223 , boost::accumulators::sample = a1
224 )
225 )
226 )
227 {
228 // Add-ref the Features that the user has specified
229 this->template visit_if<detail::contains_feature_of_<Features> >(
230 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this)
231 );
232 }
233
234 // ... other overloads generated by Boost.Preprocessor:
235
236 /// INTERNAL ONLY
237 ///
238#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \
239 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
240 accumulator_set( \
241 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
242 , typename boost::enable_if< \
243 parameter::is_argument_pack<A0> \
244 , detail::_enabler \
245 >::type = detail::_enabler() \
246 ) : accumulators( \
247 detail::make_acc_list( \
248 accumulators_mpl_vector() \
249 , ( \
250 boost::accumulators::accumulator = *this \
251 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
252 ) \
253 ) \
254 ) \
255 { \
256 /* Add-ref the Features that the user has specified */ \
257 this->template visit_if<detail::contains_feature_of_<Features> >( \
258 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) \
259 ); \
260 } \
261 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
262 accumulator_set( \
263 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
264 , typename boost::disable_if< \
265 parameter::is_argument_pack<A0> \
266 , detail::_enabler \
267 >::type = detail::_enabler() \
268 ) : accumulators( \
269 detail::make_acc_list( \
270 accumulators_mpl_vector() \
271 , ( \
272 boost::accumulators::accumulator = *this \
273 , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
274 ) \
275 ) \
276 ) \
277 { \
278 /* Add-ref the Features that the user has specified */ \
279 this->template visit_if<detail::contains_feature_of_<Features> >( \
280 detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) \
281 ); \
282 }
283
284 /// INTERNAL ONLY
285 ///
286 BOOST_PP_REPEAT_FROM_TO(
287 2
288 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
289 , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR
290 , _
291 )
292
293 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
294 /// \overload
295 ///
296 template<typename A1, typename A2, ...>
297 accumulator_set(A1 const &a1, A2 const &a2, ...);
298 #endif
299
300 // ... other overloads generated by Boost.Preprocessor below ...
301
302 ///////////////////////////////////////////////////////////////////////////////
303 /// Visitation
304 /// \param func UnaryFunction which is invoked with each accumulator in turn.
305 template<typename UnaryFunction>
306 void visit(UnaryFunction const &func)
307 {
308 fusion::for_each(this->accumulators, func);
309 }
310
311 ///////////////////////////////////////////////////////////////////////////////
312 /// Conditional visitation
313 /// \param func UnaryFunction which is invoked with each accumulator in turn,
314 /// provided the accumulator satisfies the MPL predicate FilterPred.
315 template<typename FilterPred, typename UnaryFunction>
316 void visit_if(UnaryFunction const &func)
317 {
318 fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators);
319 fusion::for_each(filtered_accs, func);
320 }
321
322 ///////////////////////////////////////////////////////////////////////////////
323 /// The return type of the operator() overloads is void.
324 typedef void result_type;
325
326 ///////////////////////////////////////////////////////////////////////////////
327 /// Accumulation
328 /// \param a1 Optional named parameter to be passed to all the accumulators
329 void operator ()()
330 {
331 this->visit(
332 detail::make_accumulator_visitor(
333 boost::accumulators::accumulator = *this
334 )
335 );
336 }
337
338 // ... other overloads generated by Boost.Preprocessor:
339
340 /// INTERNAL ONLY
341 ///
342#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \
343 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
344 void operator ()( \
345 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
346 , typename boost::enable_if< \
347 parameter::is_argument_pack<A0> \
348 , detail::_enabler \
349 >::type = detail::_enabler() \
350 ) \
351 { \
352 this->visit( \
353 detail::make_accumulator_visitor( \
354 ( \
355 boost::accumulators::accumulator = *this \
356 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
357 ) \
358 ) \
359 ); \
360 } \
361 template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
362 void operator ()( \
363 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a) \
364 , typename boost::disable_if< \
365 parameter::is_argument_pack<A0> \
366 , detail::_enabler \
367 >::type = detail::_enabler() \
368 ) \
369 { \
370 this->visit( \
371 detail::make_accumulator_visitor( \
372 ( \
373 boost::accumulators::accumulator = *this \
374 , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
375 ) \
376 ) \
377 ); \
378 }
379
380 /// INTERNAL ONLY
381 ///
382 BOOST_PP_REPEAT_FROM_TO(
383 1
384 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
385 , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP
386 , _
387 )
388
389 #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
390 /// \overload
391 ///
392 template<typename A1, typename A2, ...>
393 void operator ()(A1 const &a1, A2 const &a2, ...);
394 #endif
395
396 ///////////////////////////////////////////////////////////////////////////////
397 /// Extraction
398 template<typename Feature>
399 struct apply
400 : fusion::result_of::value_of<
401 typename fusion::result_of::find_if<
402 accumulators_type
403 , detail::matches_feature<Feature>
404 >::type
405 >
406 {
407 };
408
409 ///////////////////////////////////////////////////////////////////////////////
410 /// Extraction
411 template<typename Feature>
412 typename apply<Feature>::type &extract()
413 {
414 return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
415 }
416
417 /// \overload
418 template<typename Feature>
419 typename apply<Feature>::type const &extract() const
420 {
421 return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
422 }
423
424 ///////////////////////////////////////////////////////////////////////////////
425 /// Drop
426 template<typename Feature>
427 void drop()
428 {
429 // You can only drop the features that you have specified explicitly
430 typedef typename apply<Feature>::type the_accumulator;
431 BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>));
432
433 typedef
434 typename feature_of<typename as_feature<Feature>::type>::type
435 the_feature;
436
437 (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))
438 .drop(boost::accumulators::accumulator = *this);
439
440 // Also drop accumulators that this feature depends on
441 typedef typename the_feature::dependencies dependencies;
442 this->template visit_if<detail::contains_feature_of_<dependencies> >(
443 detail::make_drop_visitor(boost::accumulators::accumulator = *this)
444 );
445 }
446
447 // make the accumulator set serializeable
448 template<class Archive>
449 void serialize(Archive & ar, const unsigned int file_version)
450 {
451 detail::serialize_accumulator<Archive> serializer(ar, file_version);
452 fusion::for_each(this->accumulators, serializer);
453 }
454
455private:
456
457 accumulators_type accumulators;
458};
459
460#ifdef _MSC_VER
461#pragma warning(pop)
462#endif
463
464///////////////////////////////////////////////////////////////////////////////
465// find_accumulator
466// find an accumulator in an accumulator_set corresponding to a feature
467template<typename Feature, typename AccumulatorSet>
468typename mpl::apply<AccumulatorSet, Feature>::type &
469find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet))
470{
471 return acc.template extract<Feature>();
472}
473
474/// \overload
475template<typename Feature, typename AccumulatorSet>
476typename mpl::apply<AccumulatorSet, Feature>::type const &
477find_accumulator(AccumulatorSet const &acc)
478{
479 return acc.template extract<Feature>();
480}
481
482template<typename Feature, typename AccumulatorSet>
483typename mpl::apply<AccumulatorSet, Feature>::type::result_type
484extract_result(AccumulatorSet const &acc)
485{
486 return find_accumulator<Feature>(acc).result(
487 boost::accumulators::accumulator = acc
488 );
489}
490
491///////////////////////////////////////////////////////////////////////////////
492// extract_result
493// extract a result from an accumulator set
494/// INTERNAL ONLY
495///
496#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _) \
497 template< \
498 typename Feature \
499 , typename AccumulatorSet \
500 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
501 > \
502 typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
503 extract_result( \
504 AccumulatorSet const &acc \
505 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
506 , typename boost::enable_if< \
507 parameter::is_argument_pack<A0> \
508 , detail::_enabler \
509 >::type \
510 ) \
511 { \
512 return find_accumulator<Feature>(acc).result( \
513 ( \
514 boost::accumulators::accumulator = acc \
515 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
516 ) \
517 ); \
518 } \
519 template< \
520 typename Feature \
521 , typename AccumulatorSet \
522 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
523 > \
524 typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
525 extract_result( \
526 AccumulatorSet const &acc \
527 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
528 , typename boost::disable_if< \
529 parameter::is_argument_pack<A0> \
530 , detail::_enabler \
531 >::type \
532 ) \
533 { \
534 return find_accumulator<Feature>(acc).result(( \
535 boost::accumulators::accumulator = acc \
536 , boost::accumulators::sample = BOOST_PP_ENUM_PARAMS_Z(z, n, a) \
537 )); \
538 }
539
540BOOST_PP_REPEAT_FROM_TO(
541 1
542 , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
543 , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN
544 , _
545)
546
547}} // namespace boost::accumulators
548
549#endif
550

source code of boost/libs/accumulators/include/boost/accumulators/framework/accumulator_set.hpp