/Src/Dependencies/Boost/boost/accumulators/framework/accumulator_set.hpp

http://hadesmem.googlecode.com/ · C++ Header · 401 lines · 269 code · 48 blank · 84 comment · 0 complexity · c72c5e2f2779fb2d8d6078c1b4a90d5e MD5 · raw file

  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. #ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
  8. #define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005
  9. #include <boost/version.hpp>
  10. #include <boost/mpl/apply.hpp>
  11. #include <boost/mpl/assert.hpp>
  12. #include <boost/mpl/protect.hpp>
  13. #include <boost/mpl/identity.hpp>
  14. #include <boost/mpl/is_sequence.hpp>
  15. #include <boost/type_traits/is_same.hpp>
  16. #include <boost/type_traits/is_base_and_derived.hpp>
  17. #include <boost/parameter/parameters.hpp>
  18. #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  19. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  20. #include <boost/accumulators/accumulators_fwd.hpp>
  21. #include <boost/accumulators/framework/depends_on.hpp>
  22. #include <boost/accumulators/framework/accumulator_concept.hpp>
  23. #include <boost/accumulators/framework/parameters/accumulator.hpp>
  24. #include <boost/accumulators/framework/parameters/sample.hpp>
  25. #include <boost/accumulators/framework/accumulators/external_accumulator.hpp>
  26. #include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp>
  27. #include <boost/fusion/include/any.hpp>
  28. #include <boost/fusion/include/find_if.hpp>
  29. #include <boost/fusion/include/for_each.hpp>
  30. #include <boost/fusion/include/filter_view.hpp>
  31. namespace boost { namespace accumulators
  32. {
  33. namespace detail
  34. {
  35. ///////////////////////////////////////////////////////////////////////////////
  36. // accumulator_visitor
  37. // wrap a boost::parameter argument pack in a Fusion extractor object
  38. template<typename Args>
  39. struct accumulator_visitor
  40. {
  41. explicit accumulator_visitor(Args const &a)
  42. : args(a)
  43. {
  44. }
  45. template<typename Accumulator>
  46. void operator ()(Accumulator &accumulator) const
  47. {
  48. accumulator(this->args);
  49. }
  50. private:
  51. accumulator_visitor &operator =(accumulator_visitor const &);
  52. Args const &args;
  53. };
  54. template<typename Args>
  55. inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args)
  56. {
  57. return accumulator_visitor<Args>(args);
  58. }
  59. typedef
  60. parameter::parameters<
  61. parameter::required<tag::accumulator>
  62. , parameter::optional<tag::sample>
  63. // ... and others which are not specified here...
  64. >
  65. accumulator_params;
  66. ///////////////////////////////////////////////////////////////////////////////
  67. // accumulator_set_base
  68. struct accumulator_set_base
  69. {
  70. };
  71. ///////////////////////////////////////////////////////////////////////////////
  72. // is_accumulator_set
  73. template<typename T>
  74. struct is_accumulator_set
  75. : is_base_and_derived<accumulator_set_base, T>
  76. {
  77. };
  78. } // namespace detail
  79. #ifdef _MSC_VER
  80. #pragma warning(push)
  81. #pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
  82. #endif
  83. ///////////////////////////////////////////////////////////////////////////////
  84. /// \brief A set of accumulators.
  85. ///
  86. /// accumulator_set resolves the dependencies between features and ensures that
  87. /// the accumulators in the set are updated in the proper order.
  88. ///
  89. /// acccumulator_set provides a general mechanism to visit the accumulators
  90. /// in the set in order, with or without a filter. You can also fetch a reference
  91. /// to an accumulator that corresponds to a feature.
  92. ///
  93. template<typename Sample, typename Features, typename Weight>
  94. struct accumulator_set
  95. : detail::accumulator_set_base
  96. {
  97. typedef Sample sample_type; ///< The type of the samples that will be accumulated
  98. typedef Features features_type; ///< An MPL sequence of the features that should be accumulated.
  99. typedef Weight weight_type; ///< The type of the weight parameter. Must be a scalar. Defaults to void.
  100. /// INTERNAL ONLY
  101. ///
  102. typedef
  103. typename detail::make_accumulator_tuple<
  104. Features
  105. , Sample
  106. , Weight
  107. >::type
  108. accumulators_mpl_vector;
  109. // generate a fusion::list of accumulators
  110. /// INTERNAL ONLY
  111. ///
  112. typedef
  113. typename detail::meta::make_acc_list<
  114. accumulators_mpl_vector
  115. >::type
  116. accumulators_type;
  117. /// INTERNAL ONLY
  118. ///
  119. //BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>));
  120. ///////////////////////////////////////////////////////////////////////////////
  121. /// default-construct all contained accumulators
  122. accumulator_set()
  123. : accumulators(
  124. detail::make_acc_list(
  125. accumulators_mpl_vector()
  126. , detail::accumulator_params()(*this)
  127. )
  128. )
  129. {
  130. // Add-ref the Features that the user has specified
  131. this->template visit_if<detail::contains_feature_of_<Features> >(
  132. detail::make_add_ref_visitor(detail::accumulator_params()(*this))
  133. );
  134. }
  135. /// \overload
  136. ///
  137. /// \param a1 Optional named parameter to be passed to all the accumulators
  138. template<typename A1>
  139. explicit accumulator_set(A1 const &a1)
  140. : accumulators(
  141. detail::make_acc_list(
  142. accumulators_mpl_vector()
  143. , detail::accumulator_params()(*this, a1)
  144. )
  145. )
  146. {
  147. // Add-ref the Features that the user has specified
  148. this->template visit_if<detail::contains_feature_of_<Features> >(
  149. detail::make_add_ref_visitor(detail::accumulator_params()(*this))
  150. );
  151. }
  152. // ... other overloads generated by Boost.Preprocessor:
  153. /// INTERNAL ONLY
  154. ///
  155. #define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \
  156. template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
  157. accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \
  158. : accumulators( \
  159. detail::make_acc_list( \
  160. accumulators_mpl_vector() \
  161. , detail::accumulator_params()( \
  162. *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
  163. ) \
  164. ) \
  165. ) \
  166. { \
  167. /* Add-ref the Features that the user has specified */ \
  168. this->template visit_if<detail::contains_feature_of_<Features> >( \
  169. detail::make_add_ref_visitor(detail::accumulator_params()(*this)) \
  170. ); \
  171. }
  172. /// INTERNAL ONLY
  173. ///
  174. BOOST_PP_REPEAT_FROM_TO(
  175. 2
  176. , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
  177. , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR
  178. , _
  179. )
  180. #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
  181. /// \overload
  182. ///
  183. template<typename A1, typename A2, ...>
  184. accumulator_set(A1 const &a1, A2 const &a2, ...);
  185. #endif
  186. // ... other overloads generated by Boost.Preprocessor below ...
  187. ///////////////////////////////////////////////////////////////////////////////
  188. /// Visitation
  189. /// \param func UnaryFunction which is invoked with each accumulator in turn.
  190. template<typename UnaryFunction>
  191. void visit(UnaryFunction const &func)
  192. {
  193. fusion::for_each(this->accumulators, func);
  194. }
  195. ///////////////////////////////////////////////////////////////////////////////
  196. /// Conditional visitation
  197. /// \param func UnaryFunction which is invoked with each accumulator in turn,
  198. /// provided the accumulator satisfies the MPL predicate FilterPred.
  199. template<typename FilterPred, typename UnaryFunction>
  200. void visit_if(UnaryFunction const &func)
  201. {
  202. fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators);
  203. fusion::for_each(filtered_accs, func);
  204. }
  205. ///////////////////////////////////////////////////////////////////////////////
  206. /// The return type of the operator() overloads is void.
  207. typedef void result_type;
  208. ///////////////////////////////////////////////////////////////////////////////
  209. /// Accumulation
  210. /// \param a1 Optional named parameter to be passed to all the accumulators
  211. void operator ()()
  212. {
  213. this->visit(
  214. detail::make_accumulator_visitor(
  215. detail::accumulator_params()(*this)
  216. )
  217. );
  218. }
  219. template<typename A1>
  220. void operator ()(A1 const &a1)
  221. {
  222. this->visit(
  223. detail::make_accumulator_visitor(
  224. detail::accumulator_params()(*this, a1)
  225. )
  226. );
  227. }
  228. // ... other overloads generated by Boost.Preprocessor:
  229. /// INTERNAL ONLY
  230. ///
  231. #define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \
  232. template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
  233. void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \
  234. { \
  235. this->visit( \
  236. detail::make_accumulator_visitor( \
  237. detail::accumulator_params()( \
  238. *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
  239. ) \
  240. ) \
  241. ); \
  242. }
  243. /// INTERNAL ONLY
  244. ///
  245. BOOST_PP_REPEAT_FROM_TO(
  246. 2
  247. , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
  248. , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP
  249. , _
  250. )
  251. #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED
  252. /// \overload
  253. ///
  254. template<typename A1, typename A2, ...>
  255. void operator ()(A1 const &a1, A2 const &a2, ...);
  256. #endif
  257. ///////////////////////////////////////////////////////////////////////////////
  258. /// Extraction
  259. template<typename Feature>
  260. struct apply
  261. : fusion::result_of::value_of<
  262. typename fusion::result_of::find_if<
  263. accumulators_type
  264. , detail::matches_feature<Feature>
  265. >::type
  266. >
  267. {
  268. };
  269. ///////////////////////////////////////////////////////////////////////////////
  270. /// Extraction
  271. template<typename Feature>
  272. typename apply<Feature>::type &extract()
  273. {
  274. return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
  275. }
  276. /// \overload
  277. template<typename Feature>
  278. typename apply<Feature>::type const &extract() const
  279. {
  280. return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators);
  281. }
  282. ///////////////////////////////////////////////////////////////////////////////
  283. /// Drop
  284. template<typename Feature>
  285. void drop()
  286. {
  287. // You can only drop the features that you have specified explicitly
  288. typedef typename apply<Feature>::type the_accumulator;
  289. BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>));
  290. typedef
  291. typename feature_of<typename as_feature<Feature>::type>::type
  292. the_feature;
  293. (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators))
  294. .drop(detail::accumulator_params()(*this));
  295. // Also drop accumulators that this feature depends on
  296. typedef typename the_feature::dependencies dependencies;
  297. this->template visit_if<detail::contains_feature_of_<dependencies> >(
  298. detail::make_drop_visitor(detail::accumulator_params()(*this))
  299. );
  300. }
  301. private:
  302. accumulators_type accumulators;
  303. };
  304. #ifdef _MSC_VER
  305. #pragma warning(pop)
  306. #endif
  307. ///////////////////////////////////////////////////////////////////////////////
  308. // find_accumulator
  309. // find an accumulator in an accumulator_set corresponding to a feature
  310. template<typename Feature, typename AccumulatorSet>
  311. typename mpl::apply<AccumulatorSet, Feature>::type &
  312. find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet))
  313. {
  314. return acc.template extract<Feature>();
  315. }
  316. /// \overload
  317. template<typename Feature, typename AccumulatorSet>
  318. typename mpl::apply<AccumulatorSet, Feature>::type const &
  319. find_accumulator(AccumulatorSet const &acc)
  320. {
  321. return acc.template extract<Feature>();
  322. }
  323. ///////////////////////////////////////////////////////////////////////////////
  324. // extract_result
  325. // extract a result from an accumulator set
  326. /// INTERNAL ONLY
  327. ///
  328. #define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _) \
  329. template< \
  330. typename Feature \
  331. , typename AccumulatorSet \
  332. BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \
  333. > \
  334. typename mpl::apply<AccumulatorSet, Feature>::type::result_type \
  335. extract_result( \
  336. AccumulatorSet const &acc \
  337. BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \
  338. ) \
  339. { \
  340. return find_accumulator<Feature>(acc).result( \
  341. detail::accumulator_params()( \
  342. acc \
  343. BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \
  344. ) \
  345. ); \
  346. }
  347. BOOST_PP_REPEAT(
  348. BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS)
  349. , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN
  350. , _
  351. )
  352. }} // namespace boost::accumulators
  353. #endif