nest.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*=============================================================================
  2. Copyright (C) 2015 Kohei Takahshi
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. ==============================================================================*/
  6. #include <utility>
  7. #include <boost/config.hpp>
  8. #include <boost/fusion/include/adapt_struct.hpp>
  9. #include <boost/fusion/include/as_deque.hpp>
  10. #include <boost/fusion/include/as_list.hpp>
  11. #include <boost/fusion/include/as_vector.hpp>
  12. #include <boost/fusion/include/begin.hpp>
  13. #include <boost/fusion/include/is_sequence.hpp>
  14. #include <boost/fusion/include/size.hpp>
  15. #include <boost/fusion/include/value_of.hpp>
  16. #include <boost/type_traits/integral_constant.hpp>
  17. #include <boost/type_traits/remove_const.hpp>
  18. #include <boost/type_traits/remove_reference.hpp>
  19. #include "fixture.hpp"
  20. namespace test_detail
  21. {
  22. struct adapted_sequence
  23. {
  24. adapted_sequence() : value_() {}
  25. explicit adapted_sequence(int value) : value_(value) {}
  26. int value_;
  27. };
  28. bool operator==(adapted_sequence const& lhs, adapted_sequence const& rhs)
  29. {
  30. return lhs.value_ == rhs.value_;
  31. }
  32. bool operator!=(adapted_sequence const& lhs, adapted_sequence const& rhs)
  33. {
  34. return lhs.value_ != rhs.value_;
  35. }
  36. template <template <typename> class Scenario>
  37. struct can_convert_using
  38. {
  39. template <typename T>
  40. struct to
  41. {
  42. static bool can_convert_(boost::true_type /* skip */)
  43. {
  44. return true;
  45. }
  46. static bool can_convert_(boost::false_type /* skip */)
  47. {
  48. using namespace boost::fusion;
  49. return
  50. run<Scenario<T> >(typename result_of::as_deque<T>::type()) &&
  51. run<Scenario<T> >(typename result_of::as_list<T>::type()) &&
  52. run<Scenario<T> >(typename result_of::as_vector<T>::type());
  53. }
  54. template <typename Source, typename Expected>
  55. bool operator()(Source const&, Expected const&) const
  56. {
  57. // bug when converting single element sequences in C++03 and
  58. // C++11...
  59. // not_<not_<is_convertible<sequence<sequence<int>>, int >
  60. // is invalid check
  61. typedef typename ::boost::fusion::result_of::size<T>::type seq_size;
  62. return can_convert_(
  63. boost::integral_constant<bool, seq_size::value == 1>()
  64. );
  65. }
  66. };
  67. };
  68. template <typename T>
  69. struct can_construct_from_elements
  70. {
  71. template <typename Source, typename Expected>
  72. bool operator()(Source const&, Expected const&) const
  73. {
  74. // constructing a nested sequence of one is the complicated case to
  75. // disambiguate from a conversion-copy, so focus on that
  76. typedef typename boost::fusion::result_of::size<T>::type seq_size;
  77. return can_construct_(
  78. boost::integral_constant<int, seq_size::value>()
  79. );
  80. }
  81. template <int Size>
  82. static bool can_construct_(boost::integral_constant<int, Size>)
  83. {
  84. return Size == 0 || Size == 2 || Size == 3;
  85. }
  86. static bool can_construct_(boost::integral_constant<int, 1>)
  87. {
  88. typedef typename ::boost::remove_reference<
  89. typename ::boost::remove_const<
  90. typename ::boost::fusion::result_of::value_of<
  91. typename ::boost::fusion::result_of::begin<T>::type
  92. >::type
  93. >::type
  94. >::type element;
  95. return run< can_construct<T> >(element(), T());
  96. }
  97. };
  98. template <typename T>
  99. struct can_nest
  100. {
  101. template <typename Source, typename Expected>
  102. bool operator()(Source const& source, Expected const& expected)
  103. {
  104. return
  105. run< can_copy<T> >(source, expected) &&
  106. run< can_convert_using<can_copy>::to<T> >(source, expected) &&
  107. run< can_construct_from_elements<T> >(source, expected);
  108. }
  109. };
  110. } // test_detail
  111. BOOST_FUSION_ADAPT_STRUCT(test_detail::adapted_sequence, (int, data))
  112. template <template <typename> class Scenario>
  113. void
  114. test()
  115. {
  116. using namespace test_detail;
  117. BOOST_TEST(boost::fusion::traits::is_sequence<adapted_sequence>::value);
  118. BOOST_TEST(boost::fusion::size(adapted_sequence()) == 1);
  119. BOOST_TEST((
  120. run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<> > > >(
  121. FUSION_SEQUENCE< FUSION_SEQUENCE<> >()
  122. )
  123. ));
  124. BOOST_TEST((
  125. run< Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, int> > >(
  126. FUSION_SEQUENCE< FUSION_SEQUENCE<>, int>(FUSION_SEQUENCE<>(), 325)
  127. )
  128. ));
  129. BOOST_TEST((
  130. run< Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<> > > >(
  131. FUSION_SEQUENCE< int, FUSION_SEQUENCE<> >(325, FUSION_SEQUENCE<>())
  132. )
  133. ));
  134. BOOST_TEST((
  135. run< Scenario<FUSION_SEQUENCE<int, FUSION_SEQUENCE<>, float> > >(
  136. FUSION_SEQUENCE<int, FUSION_SEQUENCE<> , float>(
  137. 325, FUSION_SEQUENCE<>(), 2.0f
  138. )
  139. )
  140. ));
  141. BOOST_TEST((
  142. run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<int> > > >(
  143. FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(400))
  144. )
  145. ));
  146. BOOST_TEST((
  147. run< Scenario< FUSION_SEQUENCE<adapted_sequence> > >(
  148. FUSION_SEQUENCE<adapted_sequence>(adapted_sequence(400))
  149. )
  150. ));
  151. BOOST_TEST((
  152. run< Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, int> > >(
  153. FUSION_SEQUENCE<FUSION_SEQUENCE<int>, int>(
  154. FUSION_SEQUENCE<int>(325), 400
  155. )
  156. )
  157. ));
  158. BOOST_TEST((
  159. run< Scenario<FUSION_SEQUENCE<adapted_sequence, int> > >(
  160. FUSION_SEQUENCE<adapted_sequence, int>(adapted_sequence(325), 400)
  161. )
  162. ));
  163. BOOST_TEST((
  164. run< Scenario< FUSION_SEQUENCE< int, FUSION_SEQUENCE<int> > > >(
  165. FUSION_SEQUENCE< int, FUSION_SEQUENCE<int> >(
  166. 325, FUSION_SEQUENCE<int>(400)
  167. )
  168. )
  169. ));
  170. BOOST_TEST((
  171. run< Scenario< FUSION_SEQUENCE<int, adapted_sequence> > >(
  172. FUSION_SEQUENCE<int, adapted_sequence>(325, adapted_sequence(450))
  173. )
  174. ));
  175. BOOST_TEST((
  176. run< Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<int>, int> > >(
  177. FUSION_SEQUENCE<int, FUSION_SEQUENCE<int>, int>(
  178. 500, FUSION_SEQUENCE<int>(350), 200
  179. )
  180. )
  181. ));
  182. BOOST_TEST((
  183. run< Scenario< FUSION_SEQUENCE<int, adapted_sequence, int> > >(
  184. FUSION_SEQUENCE<int, adapted_sequence, int>(
  185. 300, adapted_sequence(500), 400)
  186. )
  187. ));
  188. BOOST_TEST((
  189. run< Scenario< FUSION_SEQUENCE< FUSION_SEQUENCE<int, int> > > >(
  190. FUSION_SEQUENCE< FUSION_SEQUENCE<int, int> >(
  191. FUSION_SEQUENCE<int, int>(450, 500)
  192. )
  193. )
  194. ));
  195. BOOST_TEST((
  196. run< Scenario< FUSION_SEQUENCE<FUSION_SEQUENCE<int, int>, int> > >(
  197. FUSION_SEQUENCE<FUSION_SEQUENCE<int, int>, int>(
  198. FUSION_SEQUENCE<int, int>(450, 500), 150
  199. )
  200. )
  201. ));
  202. BOOST_TEST((
  203. run< Scenario< FUSION_SEQUENCE< int, FUSION_SEQUENCE<int, int> > > >(
  204. FUSION_SEQUENCE< int, FUSION_SEQUENCE<int, int> >(
  205. 450, FUSION_SEQUENCE<int, int>(500, 150)
  206. )
  207. )
  208. ));
  209. BOOST_TEST((
  210. run<Scenario< FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, int>, int> > >(
  211. FUSION_SEQUENCE<int, FUSION_SEQUENCE<int, int>, int>(
  212. 150, FUSION_SEQUENCE<int, int>(250, 350), 450
  213. )
  214. )
  215. ));
  216. BOOST_TEST((
  217. run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<> > > >(
  218. FUSION_SEQUENCE< FUSION_SEQUENCE<>, FUSION_SEQUENCE<> >(
  219. FUSION_SEQUENCE<>(), FUSION_SEQUENCE<>()
  220. )
  221. )
  222. ));
  223. BOOST_TEST((
  224. run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<> > > >(
  225. FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<> >(
  226. FUSION_SEQUENCE<int>(150), FUSION_SEQUENCE<>()
  227. )
  228. )
  229. ));
  230. BOOST_TEST((
  231. run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<>, FUSION_SEQUENCE<int> > > >(
  232. FUSION_SEQUENCE< FUSION_SEQUENCE<>, FUSION_SEQUENCE<int> >(
  233. FUSION_SEQUENCE<>(), FUSION_SEQUENCE<int>(500)
  234. )
  235. )
  236. ));
  237. BOOST_TEST((
  238. run<Scenario<FUSION_SEQUENCE<FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> > > >(
  239. FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int> >(
  240. FUSION_SEQUENCE<int>(155), FUSION_SEQUENCE<int>(255)
  241. )
  242. )
  243. ));
  244. BOOST_TEST((
  245. run< Scenario<
  246. FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int> >
  247. > >(
  248. FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int> >(
  249. FUSION_SEQUENCE<int, int>(222, 333), FUSION_SEQUENCE<int>(444)
  250. )
  251. )
  252. ));
  253. BOOST_TEST((
  254. run< Scenario<
  255. FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int, int> >
  256. > >(
  257. FUSION_SEQUENCE< FUSION_SEQUENCE<int>, FUSION_SEQUENCE<int, int> >(
  258. FUSION_SEQUENCE<int>(100), FUSION_SEQUENCE<int, int>(300, 400)
  259. )
  260. )
  261. ));
  262. BOOST_TEST((
  263. run< Scenario<
  264. FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> >
  265. > >(
  266. FUSION_SEQUENCE< FUSION_SEQUENCE<int, int>, FUSION_SEQUENCE<int, int> >(
  267. FUSION_SEQUENCE<int, int>(600, 700)
  268. , FUSION_SEQUENCE<int, int>(800, 900)
  269. )
  270. )
  271. ));
  272. // Ignore desired scenario, and cheat to make these work
  273. BOOST_TEST((
  274. run< can_lvalue_construct< FUSION_SEQUENCE<FUSION_SEQUENCE<>&> > >(
  275. FUSION_SEQUENCE<>()
  276. , FUSION_SEQUENCE< FUSION_SEQUENCE<> >()
  277. )
  278. ));
  279. BOOST_TEST((
  280. run< can_construct< FUSION_SEQUENCE<const FUSION_SEQUENCE<>&> > >(
  281. FUSION_SEQUENCE<>()
  282. , FUSION_SEQUENCE< FUSION_SEQUENCE<> >()
  283. )
  284. ));
  285. BOOST_TEST((
  286. run< can_lvalue_construct< FUSION_SEQUENCE<FUSION_SEQUENCE<int>&> > >(
  287. FUSION_SEQUENCE<int>(300)
  288. , FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(300))
  289. )
  290. ));
  291. BOOST_TEST((
  292. run< can_construct< FUSION_SEQUENCE<const FUSION_SEQUENCE<int>&> > >(
  293. FUSION_SEQUENCE<int>(400)
  294. , FUSION_SEQUENCE< FUSION_SEQUENCE<int> >(FUSION_SEQUENCE<int>(400))
  295. )
  296. ));
  297. }