triple.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2011 Nathan Ridge
  4. Copyright (c) 2006 Dan Marsden
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ==============================================================================*/
  8. /*=============================================================================
  9. An implementation of a std::pair like triple<T0, T1, T2>
  10. We use fusion::sequence_facade and fusion::iterator_facade
  11. to make our triple a fully conforming Boost.Fusion random
  12. traversal sequence.
  13. ==============================================================================*/
  14. #include <boost/detail/lightweight_test.hpp>
  15. #include <boost/fusion/sequence/sequence_facade.hpp>
  16. #include <boost/fusion/iterator/iterator_facade.hpp>
  17. #include <boost/fusion/sequence/intrinsic.hpp>
  18. #include <boost/fusion/iterator.hpp>
  19. #include <boost/fusion/support/category_of.hpp>
  20. #include <boost/fusion/algorithm/iteration/fold.hpp>
  21. #include <boost/mpl/int.hpp>
  22. #include <boost/mpl/identity.hpp>
  23. #include <boost/mpl/minus.hpp>
  24. #include <boost/mpl/assert.hpp>
  25. #include <boost/type_traits/is_const.hpp>
  26. #include <boost/type_traits/is_same.hpp>
  27. #include <string>
  28. namespace mpl = boost::mpl;
  29. namespace fusion = boost::fusion;
  30. namespace demo
  31. {
  32. template<typename Seq, int N>
  33. struct triple_iterator
  34. : fusion::iterator_facade<triple_iterator<Seq, N>,
  35. fusion::random_access_traversal_tag>
  36. {
  37. typedef mpl::int_<N> index;
  38. typedef Seq sequence_type;
  39. triple_iterator(Seq& seq)
  40. : seq_(seq) {}
  41. Seq& seq_;
  42. template<typename T>
  43. struct value_of;
  44. template<typename Sq>
  45. struct value_of<triple_iterator<Sq, 0> >
  46. : mpl::identity<typename Sq::t0_type>
  47. {};
  48. template<typename Sq>
  49. struct value_of<triple_iterator<Sq, 1> >
  50. : mpl::identity<typename Sq::t1_type>
  51. {};
  52. template<typename Sq>
  53. struct value_of<triple_iterator<Sq, 2> >
  54. : mpl::identity<typename Sq::t2_type>
  55. {};
  56. template<typename T>
  57. struct deref;
  58. template <typename Sq>
  59. struct deref<triple_iterator<Sq, 0> >
  60. {
  61. typedef typename Sq::t0_type& type;
  62. static type
  63. call(triple_iterator<Sq, 0> const& iter)
  64. {
  65. return iter.seq_.t0;
  66. }
  67. };
  68. template <typename Sq>
  69. struct deref<triple_iterator<Sq, 0> const>
  70. {
  71. typedef typename Sq::t0_type const& type;
  72. static type
  73. call(triple_iterator<Sq, 0> const& iter)
  74. {
  75. return iter.seq_.t0;
  76. }
  77. };
  78. template <typename Sq>
  79. struct deref<triple_iterator<Sq, 1> >
  80. {
  81. typedef typename Sq::t1_type& type;
  82. static type
  83. call(triple_iterator<Sq, 1> const& iter)
  84. {
  85. return iter.seq_.t1;
  86. }
  87. };
  88. template <typename Sq>
  89. struct deref<triple_iterator<Sq, 1> const>
  90. {
  91. typedef typename Sq::t1_type const& type;
  92. static type
  93. call(triple_iterator<Sq, 1> const& iter)
  94. {
  95. return iter.seq_.t1;
  96. }
  97. };
  98. template <typename Sq>
  99. struct deref<triple_iterator<Sq, 2> >
  100. {
  101. typedef typename Sq::t2_type& type;
  102. static type
  103. call(triple_iterator<Sq, 2> const& iter)
  104. {
  105. return iter.seq_.t2;
  106. }
  107. };
  108. template <typename Sq>
  109. struct deref<triple_iterator<Sq, 2> const>
  110. {
  111. typedef typename Sq::t2_type const& type;
  112. static type
  113. call(triple_iterator<Sq, 2> const& iter)
  114. {
  115. return iter.seq_.t2;
  116. }
  117. };
  118. template<typename It>
  119. struct next
  120. {
  121. typedef triple_iterator<
  122. typename It::sequence_type, It::index::value + 1>
  123. type;
  124. static type call(It const& it)
  125. {
  126. return type(it.seq_);
  127. }
  128. };
  129. template<typename It>
  130. struct prior
  131. {
  132. typedef triple_iterator<
  133. typename It::sequence_type, It::index::value - 1>
  134. type;
  135. static type call(It const& it)
  136. {
  137. return type(it.seq_);
  138. }
  139. };
  140. template<typename It1, typename It2>
  141. struct distance
  142. {
  143. typedef typename mpl::minus<
  144. typename It2::index, typename It1::index>::type
  145. type;
  146. static type call(It1 const& it1, It2 const& it2)
  147. {
  148. return type();
  149. }
  150. };
  151. template<typename It, typename M>
  152. struct advance
  153. {
  154. typedef triple_iterator<
  155. typename It::sequence_type,
  156. It::index::value + M::value>
  157. type;
  158. static type call(It const& it)
  159. {
  160. return type(it.seq_);
  161. }
  162. };
  163. };
  164. template<typename T0, typename T1, typename T2>
  165. struct triple
  166. : fusion::sequence_facade<triple<T0, T1, T2>,
  167. fusion::random_access_traversal_tag>
  168. {
  169. triple(T0 const& t0, T1 const& t1, T2 const& t2)
  170. : t0(t0), t1(t1), t2(t2)
  171. {}
  172. template<typename Sq>
  173. struct begin
  174. {
  175. typedef demo::triple_iterator<Sq, 0> type;
  176. static type call(Sq& sq)
  177. {
  178. return type(sq);
  179. }
  180. };
  181. template<typename Sq>
  182. struct end
  183. {
  184. typedef demo::triple_iterator<Sq, 3> type;
  185. static type call(Sq& sq)
  186. {
  187. return type(sq);
  188. }
  189. };
  190. template<typename Sq>
  191. struct size
  192. : mpl::int_<3>
  193. {};
  194. template<typename Sq, typename N>
  195. struct value_at
  196. : value_at<Sq, mpl::int_<N::value> >
  197. {};
  198. template<typename Sq>
  199. struct value_at<Sq, mpl::int_<0> >
  200. {
  201. typedef typename Sq::t0_type type;
  202. };
  203. template<typename Sq>
  204. struct value_at<Sq, mpl::int_<1> >
  205. {
  206. typedef typename Sq::t1_type type;
  207. };
  208. template<typename Sq>
  209. struct value_at<Sq, mpl::int_<2> >
  210. {
  211. typedef typename Sq::t2_type type;
  212. };
  213. template<typename Sq, typename N>
  214. struct at
  215. : at<Sq, mpl::int_<N::value> >
  216. {};
  217. template<typename Sq>
  218. struct at<Sq, mpl::int_<0> >
  219. {
  220. typedef typename
  221. mpl::if_<
  222. boost::is_const<Sq>
  223. , typename Sq::t0_type const&
  224. , typename Sq::t0_type&
  225. >::type
  226. type;
  227. static type call(Sq& sq)
  228. {
  229. return sq.t0;
  230. }
  231. };
  232. template<typename Sq>
  233. struct at<Sq, mpl::int_<1> >
  234. {
  235. typedef typename
  236. mpl::if_<
  237. boost::is_const<Sq>
  238. , typename Sq::t1_type const&
  239. , typename Sq::t1_type&
  240. >::type
  241. type;
  242. static type call(Sq& sq)
  243. {
  244. return sq.t1;
  245. }
  246. };
  247. template<typename Sq>
  248. struct at<Sq, mpl::int_<2> >
  249. {
  250. typedef typename
  251. mpl::if_<
  252. boost::is_const<Sq>
  253. , typename Sq::t2_type const&
  254. , typename Sq::t2_type&
  255. >::type
  256. type;
  257. static type call(Sq& sq)
  258. {
  259. return sq.t2;
  260. }
  261. };
  262. typedef T0 t0_type;
  263. typedef T1 t1_type;
  264. typedef T2 t2_type;
  265. T0 t0;
  266. T1 t1;
  267. T2 t2;
  268. };
  269. }
  270. struct modifying_fold_functor
  271. {
  272. template <typename T>
  273. struct result
  274. {
  275. typedef bool type;
  276. };
  277. template <typename T>
  278. bool operator()(bool b, T&)
  279. {
  280. return b;
  281. }
  282. };
  283. struct nonmodifying_fold_functor
  284. {
  285. template <typename T>
  286. struct result
  287. {
  288. typedef bool type;
  289. };
  290. template <typename T>
  291. bool operator()(bool b, const T&)
  292. {
  293. return b;
  294. }
  295. };
  296. int main()
  297. {
  298. typedef demo::triple<int, char, std::string> my_triple;
  299. my_triple t(101, 'a', "hello");
  300. BOOST_TEST(*fusion::begin(t) == 101);
  301. BOOST_TEST(*fusion::next(fusion::begin(t)) == 'a');
  302. BOOST_TEST(*fusion::prior(fusion::end(t)) == "hello");
  303. BOOST_TEST(fusion::distance(fusion::begin(t), fusion::end(t)) == 3);
  304. BOOST_TEST(fusion::size(t) == 3);
  305. BOOST_MPL_ASSERT((boost::is_same<
  306. int, fusion::result_of::value_at_c<my_triple, 0>::type>));
  307. BOOST_MPL_ASSERT((boost::is_same<
  308. char, fusion::result_of::value_at_c<my_triple, 1>::type>));
  309. BOOST_MPL_ASSERT((boost::is_same<
  310. std::string, fusion::result_of::value_at_c<my_triple, 2>::type>));
  311. BOOST_TEST(fusion::at_c<0>(t) == 101);
  312. BOOST_TEST(fusion::at_c<1>(t) == 'a');
  313. BOOST_TEST(fusion::at_c<2>(t) == "hello");
  314. BOOST_TEST(fusion::fold(t, true, modifying_fold_functor()) == true);
  315. BOOST_TEST(fusion::fold(t, true, nonmodifying_fold_functor()) == true);
  316. return boost::report_errors();
  317. }