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