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

http://hadesmem.googlecode.com/ · C++ Header · 411 lines · 330 code · 45 blank · 36 comment · 0 complexity · 6c9d75ae93bacccd44550c1c8ef52d06 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // depends_on.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_DEPENDS_ON_HPP_EAN_28_10_2005
  8. #define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005
  9. #include <boost/version.hpp>
  10. #include <boost/mpl/end.hpp>
  11. #include <boost/mpl/map.hpp>
  12. #include <boost/mpl/fold.hpp>
  13. #include <boost/mpl/size.hpp>
  14. #include <boost/mpl/sort.hpp>
  15. #include <boost/mpl/insert.hpp>
  16. #include <boost/mpl/assert.hpp>
  17. #include <boost/mpl/remove.hpp>
  18. #include <boost/mpl/vector.hpp>
  19. #include <boost/mpl/inherit.hpp>
  20. #include <boost/mpl/identity.hpp>
  21. #include <boost/mpl/equal_to.hpp>
  22. #include <boost/mpl/contains.hpp>
  23. #include <boost/mpl/transform.hpp>
  24. #include <boost/mpl/is_sequence.hpp>
  25. #include <boost/mpl/placeholders.hpp>
  26. #include <boost/mpl/insert_range.hpp>
  27. #include <boost/mpl/transform_view.hpp>
  28. #include <boost/mpl/inherit_linearly.hpp>
  29. #include <boost/type_traits/is_base_and_derived.hpp>
  30. #include <boost/preprocessor/repetition/repeat.hpp>
  31. #include <boost/preprocessor/repetition/enum_params.hpp>
  32. #include <boost/preprocessor/facilities/intercept.hpp>
  33. #include <boost/accumulators/accumulators_fwd.hpp>
  34. #include <boost/fusion/include/next.hpp>
  35. #include <boost/fusion/include/equal_to.hpp>
  36. #include <boost/fusion/include/value_of.hpp>
  37. #include <boost/fusion/include/mpl.hpp>
  38. #include <boost/fusion/include/end.hpp>
  39. #include <boost/fusion/include/begin.hpp>
  40. #include <boost/fusion/include/cons.hpp>
  41. namespace boost { namespace accumulators
  42. {
  43. ///////////////////////////////////////////////////////////////////////////
  44. // as_feature
  45. template<typename Feature>
  46. struct as_feature
  47. {
  48. typedef Feature type;
  49. };
  50. ///////////////////////////////////////////////////////////////////////////
  51. // weighted_feature
  52. template<typename Feature>
  53. struct as_weighted_feature
  54. {
  55. typedef Feature type;
  56. };
  57. ///////////////////////////////////////////////////////////////////////////
  58. // feature_of
  59. template<typename Feature>
  60. struct feature_of
  61. {
  62. typedef Feature type;
  63. };
  64. namespace detail
  65. {
  66. ///////////////////////////////////////////////////////////////////////////
  67. // feature_tag
  68. template<typename Accumulator>
  69. struct feature_tag
  70. {
  71. typedef typename Accumulator::feature_tag type;
  72. };
  73. template<typename Feature>
  74. struct undroppable
  75. {
  76. typedef Feature type;
  77. };
  78. template<typename Feature>
  79. struct undroppable<tag::droppable<Feature> >
  80. {
  81. typedef Feature type;
  82. };
  83. // For the purpose of determining whether one feature depends on another,
  84. // disregard whether the feature is droppable or not.
  85. template<typename A, typename B>
  86. struct is_dependent_on
  87. : is_base_and_derived<
  88. typename undroppable<B>::type
  89. , typename undroppable<A>::type
  90. >
  91. {};
  92. template<typename Features>
  93. struct depends_on_base
  94. : mpl::inherit_linearly<
  95. typename mpl::sort<Features, is_dependent_on<mpl::_1, mpl::_2> >::type
  96. // Don't inherit multiply from a feature
  97. , mpl::if_<
  98. is_dependent_on<mpl::_1, mpl::_2>
  99. , mpl::_1
  100. , mpl::inherit<mpl::_1, mpl::_2>
  101. >
  102. >::type
  103. {
  104. };
  105. }
  106. ///////////////////////////////////////////////////////////////////////////
  107. /// depends_on
  108. template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)>
  109. struct depends_on
  110. : detail::depends_on_base<
  111. typename mpl::transform<
  112. mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
  113. , as_feature<mpl::_1>
  114. >::type
  115. >
  116. {
  117. typedef mpl::false_ is_weight_accumulator;
  118. typedef
  119. typename mpl::transform<
  120. mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)>
  121. , as_feature<mpl::_1>
  122. >::type
  123. dependencies;
  124. };
  125. namespace detail
  126. {
  127. template<typename Feature>
  128. struct matches_feature
  129. {
  130. template<typename Accumulator>
  131. struct apply
  132. : is_same<
  133. typename feature_of<typename as_feature<Feature>::type>::type
  134. , typename feature_of<typename as_feature<typename feature_tag<Accumulator>::type>::type>::type
  135. >
  136. {};
  137. };
  138. template<typename Features, typename Accumulator>
  139. struct contains_feature_of
  140. {
  141. typedef
  142. mpl::transform_view<Features, feature_of<as_feature<mpl::_> > >
  143. features_list;
  144. typedef
  145. typename feature_of<typename feature_tag<Accumulator>::type>::type
  146. the_feature;
  147. typedef
  148. typename mpl::contains<features_list, the_feature>::type
  149. type;
  150. };
  151. // This is to work around a bug in early versions of Fusion which caused
  152. // a compile error if contains_feature_of<List, mpl::_> is used as a
  153. // predicate to fusion::find_if
  154. template<typename Features>
  155. struct contains_feature_of_
  156. {
  157. template<typename Accumulator>
  158. struct apply
  159. : contains_feature_of<Features, Accumulator>
  160. {};
  161. };
  162. template<
  163. typename First
  164. , typename Last
  165. , bool is_empty = fusion::result_of::equal_to<First, Last>::value
  166. >
  167. struct build_acc_list;
  168. template<typename First, typename Last>
  169. struct build_acc_list<First, Last, true>
  170. {
  171. typedef fusion::nil type;
  172. template<typename Args>
  173. static fusion::nil
  174. call(Args const &, First const&, Last const&)
  175. {
  176. return fusion::nil();
  177. }
  178. };
  179. template<typename First, typename Last>
  180. struct build_acc_list<First, Last, false>
  181. {
  182. typedef
  183. build_acc_list<typename fusion::result_of::next<First>::type, Last>
  184. next_build_acc_list;
  185. typedef fusion::cons<
  186. typename fusion::result_of::value_of<First>::type
  187. , typename next_build_acc_list::type>
  188. type;
  189. template<typename Args>
  190. static type
  191. call(Args const &args, First const& f, Last const& l)
  192. {
  193. return type(args, next_build_acc_list::call(args, fusion::next(f), l));
  194. }
  195. };
  196. namespace meta
  197. {
  198. template<typename Sequence>
  199. struct make_acc_list
  200. : build_acc_list<
  201. typename fusion::result_of::begin<Sequence>::type
  202. , typename fusion::result_of::end<Sequence>::type
  203. >
  204. {};
  205. }
  206. template<typename Sequence, typename Args>
  207. typename meta::make_acc_list<Sequence>::type
  208. make_acc_list(Sequence const &seq, Args const &args)
  209. {
  210. return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq));
  211. }
  212. ///////////////////////////////////////////////////////////////////////////
  213. // checked_as_weighted_feature
  214. template<typename Feature>
  215. struct checked_as_weighted_feature
  216. {
  217. typedef typename as_feature<Feature>::type feature_type;
  218. typedef typename as_weighted_feature<feature_type>::type type;
  219. // weighted and non-weighted flavors should provide the same feature.
  220. BOOST_MPL_ASSERT((
  221. is_same<
  222. typename feature_of<feature_type>::type
  223. , typename feature_of<type>::type
  224. >
  225. ));
  226. };
  227. ///////////////////////////////////////////////////////////////////////////
  228. // as_feature_list
  229. template<typename Features, typename Weight>
  230. struct as_feature_list
  231. : mpl::transform_view<Features, checked_as_weighted_feature<mpl::_1> >
  232. {
  233. };
  234. template<typename Features>
  235. struct as_feature_list<Features, void>
  236. : mpl::transform_view<Features, as_feature<mpl::_1> >
  237. {
  238. };
  239. ///////////////////////////////////////////////////////////////////////////
  240. // accumulator_wrapper
  241. template<typename Accumulator, typename Feature>
  242. struct accumulator_wrapper
  243. : Accumulator
  244. {
  245. typedef Feature feature_tag;
  246. accumulator_wrapper(accumulator_wrapper const &that)
  247. : Accumulator(*static_cast<Accumulator const *>(&that))
  248. {
  249. }
  250. template<typename Args>
  251. accumulator_wrapper(Args const &args)
  252. : Accumulator(args)
  253. {
  254. }
  255. };
  256. ///////////////////////////////////////////////////////////////////////////
  257. // to_accumulator
  258. template<typename Feature, typename Sample, typename Weight>
  259. struct to_accumulator
  260. {
  261. typedef
  262. accumulator_wrapper<
  263. typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
  264. , Feature
  265. >
  266. type;
  267. };
  268. template<typename Feature, typename Sample, typename Weight, typename Tag, typename AccumulatorSet>
  269. struct to_accumulator<Feature, Sample, tag::external<Weight, Tag, AccumulatorSet> >
  270. {
  271. BOOST_MPL_ASSERT((is_same<Tag, void>));
  272. BOOST_MPL_ASSERT((is_same<AccumulatorSet, void>));
  273. typedef
  274. accumulator_wrapper<
  275. typename mpl::apply2<typename Feature::impl, Sample, Weight>::type
  276. , Feature
  277. >
  278. accumulator_type;
  279. typedef
  280. typename mpl::if_<
  281. typename Feature::is_weight_accumulator
  282. , accumulator_wrapper<impl::external_impl<accumulator_type, tag::weights>, Feature>
  283. , accumulator_type
  284. >::type
  285. type;
  286. };
  287. // BUGBUG work around a MPL bug wrt map insertion
  288. template<typename FeatureMap, typename Feature>
  289. struct insert_feature
  290. : mpl::eval_if<
  291. mpl::has_key<FeatureMap, typename feature_of<Feature>::type>
  292. , mpl::identity<FeatureMap>
  293. , mpl::insert<FeatureMap, mpl::pair<typename feature_of<Feature>::type, Feature> >
  294. >
  295. {
  296. };
  297. template<typename FeatureMap, typename Feature, typename Weight>
  298. struct insert_dependencies
  299. : mpl::fold<
  300. as_feature_list<typename Feature::dependencies, Weight>
  301. , FeatureMap
  302. , insert_dependencies<
  303. insert_feature<mpl::_1, mpl::_2>
  304. , mpl::_2
  305. , Weight
  306. >
  307. >
  308. {
  309. };
  310. template<typename FeatureMap, typename Features, typename Weight>
  311. struct insert_sequence
  312. : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps
  313. as_feature_list<Features, Weight>
  314. , FeatureMap
  315. , insert_feature<mpl::_1, mpl::_2>
  316. >
  317. {
  318. };
  319. template<typename Features, typename Sample, typename Weight>
  320. struct make_accumulator_tuple
  321. {
  322. typedef
  323. typename mpl::fold<
  324. as_feature_list<Features, Weight>
  325. , mpl::map0<>
  326. , mpl::if_<
  327. mpl::is_sequence<mpl::_2>
  328. , insert_sequence<mpl::_1, mpl::_2, Weight>
  329. , insert_feature<mpl::_1, mpl::_2>
  330. >
  331. >::type
  332. feature_map;
  333. // for each element in the map, add its dependencies also
  334. typedef
  335. typename mpl::fold<
  336. feature_map
  337. , feature_map
  338. , insert_dependencies<mpl::_1, mpl::second<mpl::_2>, Weight>
  339. >::type
  340. feature_map_with_dependencies;
  341. // turn the map into a vector so we can sort it
  342. typedef
  343. typename mpl::insert_range<
  344. mpl::vector<>
  345. , mpl::end<mpl::vector<> >::type
  346. , mpl::transform_view<feature_map_with_dependencies, mpl::second<mpl::_1> >
  347. >::type
  348. feature_vector_with_dependencies;
  349. // sort the features according to which is derived from which
  350. typedef
  351. typename mpl::sort<
  352. feature_vector_with_dependencies
  353. , is_dependent_on<mpl::_2, mpl::_1>
  354. >::type
  355. sorted_feature_vector;
  356. // From the vector of features, construct a vector of accumulators
  357. typedef
  358. typename mpl::transform<
  359. sorted_feature_vector
  360. , to_accumulator<mpl::_1, Sample, Weight>
  361. >::type
  362. type;
  363. };
  364. } // namespace detail
  365. }} // namespace boost::accumulators
  366. #endif