]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
92f5a8d4 TL |
12 | #include <boost/mpl/bool.hpp> |
13 | #include <boost/mpl/if.hpp> | |
7c673cae FG |
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> | |
92f5a8d4 TL |
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> | |
7c673cae | 25 | #include <boost/preprocessor/repetition/repeat_from_to.hpp> |
92f5a8d4 | 26 | #include <boost/preprocessor/repetition/enum_params.hpp> |
7c673cae | 27 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> |
92f5a8d4 | 28 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> |
7c673cae FG |
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 | ||
7c673cae FG |
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 | |
92f5a8d4 TL |
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 | |
7c673cae FG |
94 | { |
95 | }; | |
96 | ||
92f5a8d4 TL |
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 | ||
7c673cae FG |
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() | |
92f5a8d4 | 170 | , (boost::accumulators::accumulator = *this) |
7c673cae FG |
171 | ) |
172 | ) | |
173 | { | |
174 | // Add-ref the Features that the user has specified | |
175 | this->template visit_if<detail::contains_feature_of_<Features> >( | |
92f5a8d4 | 176 | detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) |
7c673cae FG |
177 | ); |
178 | } | |
179 | ||
180 | /// \overload | |
181 | /// | |
182 | /// \param a1 Optional named parameter to be passed to all the accumulators | |
183 | template<typename A1> | |
92f5a8d4 TL |
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( | |
7c673cae FG |
214 | detail::make_acc_list( |
215 | accumulators_mpl_vector() | |
92f5a8d4 TL |
216 | , ( |
217 | boost::accumulators::accumulator = *this | |
218 | , boost::accumulators::sample = a1 | |
219 | ) | |
7c673cae FG |
220 | ) |
221 | ) | |
222 | { | |
223 | // Add-ref the Features that the user has specified | |
224 | this->template visit_if<detail::contains_feature_of_<Features> >( | |
92f5a8d4 | 225 | detail::make_add_ref_visitor(boost::accumulators::accumulator = *this) |
7c673cae FG |
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)> \ | |
92f5a8d4 TL |
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( \ | |
7c673cae FG |
242 | detail::make_acc_list( \ |
243 | accumulators_mpl_vector() \ | |
92f5a8d4 TL |
244 | , ( \ |
245 | boost::accumulators::accumulator = *this \ | |
246 | BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ | |
7c673cae FG |
247 | ) \ |
248 | ) \ | |
249 | ) \ | |
250 | { \ | |
251 | /* Add-ref the Features that the user has specified */ \ | |
252 | this->template visit_if<detail::contains_feature_of_<Features> >( \ | |
92f5a8d4 TL |
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) \ | |
7c673cae FG |
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( | |
92f5a8d4 | 328 | boost::accumulators::accumulator = *this |
7c673cae FG |
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)> \ | |
92f5a8d4 TL |
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 | ) \ | |
7c673cae FG |
346 | { \ |
347 | this->visit( \ | |
348 | detail::make_accumulator_visitor( \ | |
92f5a8d4 TL |
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) \ | |
7c673cae FG |
370 | ) \ |
371 | ) \ | |
372 | ); \ | |
373 | } | |
374 | ||
375 | /// INTERNAL ONLY | |
376 | /// | |
377 | BOOST_PP_REPEAT_FROM_TO( | |
92f5a8d4 | 378 | 1 |
7c673cae FG |
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)) | |
92f5a8d4 | 433 | .drop(boost::accumulators::accumulator = *this); |
7c673cae FG |
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> >( | |
92f5a8d4 | 438 | detail::make_drop_visitor(boost::accumulators::accumulator = *this) |
7c673cae FG |
439 | ); |
440 | } | |
441 | ||
92f5a8d4 TL |
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 | ||
7c673cae FG |
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 | ||
92f5a8d4 TL |
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 | ||
7c673cae FG |
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) \ | |
92f5a8d4 TL |
501 | , typename boost::enable_if< \ |
502 | parameter::is_argument_pack<A0> \ | |
503 | , detail::_enabler \ | |
504 | >::type \ | |
7c673cae FG |
505 | ) \ |
506 | { \ | |
507 | return find_accumulator<Feature>(acc).result( \ | |
92f5a8d4 TL |
508 | ( \ |
509 | boost::accumulators::accumulator = acc \ | |
7c673cae FG |
510 | BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ |
511 | ) \ | |
512 | ); \ | |
92f5a8d4 TL |
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 | )); \ | |
7c673cae FG |
533 | } |
534 | ||
92f5a8d4 TL |
535 | BOOST_PP_REPEAT_FROM_TO( |
536 | 1 | |
537 | , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) | |
7c673cae FG |
538 | , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN |
539 | , _ | |
540 | ) | |
541 | ||
542 | }} // namespace boost::accumulators | |
543 | ||
544 | #endif |