depends_on.hpp 15 KB

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