iterable.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #ifndef BOOST_HANA_TEST_LAWS_ITERABLE_HPP
  5. #define BOOST_HANA_TEST_LAWS_ITERABLE_HPP
  6. #include <boost/hana/any_of.hpp>
  7. #include <boost/hana/assert.hpp>
  8. #include <boost/hana/at.hpp>
  9. #include <boost/hana/back.hpp>
  10. #include <boost/hana/bool.hpp>
  11. #include <boost/hana/concept/comparable.hpp>
  12. #include <boost/hana/concept/foldable.hpp>
  13. #include <boost/hana/concept/sequence.hpp>
  14. #include <boost/hana/core/make.hpp>
  15. #include <boost/hana/core/to.hpp>
  16. #include <boost/hana/core/when.hpp>
  17. #include <boost/hana/drop_front.hpp>
  18. #include <boost/hana/drop_front_exactly.hpp>
  19. #include <boost/hana/equal.hpp>
  20. #include <boost/hana/eval_if.hpp>
  21. #include <boost/hana/find_if.hpp>
  22. #include <boost/hana/for_each.hpp>
  23. #include <boost/hana/front.hpp>
  24. #include <boost/hana/functional/always.hpp>
  25. #include <boost/hana/functional/capture.hpp>
  26. #include <boost/hana/integral_constant.hpp>
  27. #include <boost/hana/is_empty.hpp>
  28. #include <boost/hana/lazy.hpp>
  29. #include <boost/hana/length.hpp>
  30. #include <boost/hana/minus.hpp>
  31. #include <boost/hana/not.hpp>
  32. #include <boost/hana/optional.hpp>
  33. #include <boost/hana/range.hpp>
  34. #include <boost/hana/tuple.hpp>
  35. #include <laws/base.hpp>
  36. namespace boost { namespace hana { namespace test {
  37. template <typename It, typename = hana::when<true>>
  38. struct TestIterable : TestIterable<It, laws> {
  39. using TestIterable<It, laws>::TestIterable;
  40. };
  41. template <typename It>
  42. struct TestIterable<It, laws> {
  43. template <typename Xs>
  44. TestIterable(Xs xs) {
  45. hana::for_each(xs, [](auto xs) {
  46. static_assert(Iterable<decltype(xs)>{}, "");
  47. BOOST_HANA_CONSTANT_CHECK(
  48. hana::is_empty(xs) ^iff^ hana::is_empty(hana::to<tuple_tag>(xs))
  49. );
  50. only_when_(hana::not_(hana::is_empty(xs)), hana::make_lazy([](auto xs) {
  51. BOOST_HANA_CHECK(hana::equal(
  52. hana::front(xs),
  53. hana::front(hana::to<tuple_tag>(xs))
  54. ));
  55. BOOST_HANA_CHECK(hana::equal(
  56. hana::to<tuple_tag>(hana::drop_front_exactly(xs)),
  57. hana::drop_front_exactly(hana::to<tuple_tag>(xs))
  58. ));
  59. // methods
  60. // back(xs) == at(xs, length(xs)-1)
  61. BOOST_HANA_CHECK(hana::equal(
  62. hana::back(xs),
  63. hana::at(xs, hana::minus(hana::length(xs), hana::size_c<1>))
  64. ));
  65. })(xs));
  66. // drop_front(xs, 0) == xs
  67. BOOST_HANA_CHECK(hana::equal(
  68. hana::drop_front(xs, size_c<0>),
  69. xs
  70. ));
  71. // at(xs, n) == front(drop_front(xs, n))
  72. hana::for_each(hana::make_range(size_c<0>, hana::length(xs)),
  73. hana::capture(xs)([](auto xs, auto n) {
  74. BOOST_HANA_CHECK(hana::equal(
  75. hana::at(xs, n),
  76. hana::front(hana::drop_front(xs, n))
  77. ));
  78. }));
  79. // Searchable
  80. hana::eval_if(hana::is_empty(xs),
  81. hana::make_lazy([](auto xs) {
  82. BOOST_HANA_CONSTANT_CHECK(
  83. hana::not_(hana::any_of(xs, hana::always(true_c)))
  84. );
  85. BOOST_HANA_CONSTANT_CHECK(hana::equal(
  86. hana::find_if(xs, hana::always(true_c)),
  87. nothing
  88. ));
  89. })(xs),
  90. hana::make_lazy([](auto xs) {
  91. BOOST_HANA_CHECK(
  92. hana::any_of(xs, hana::always(true_c))
  93. );
  94. BOOST_HANA_CHECK(
  95. hana::not_(hana::any_of(xs, hana::always(false_c)))
  96. );
  97. BOOST_HANA_CHECK(hana::equal(
  98. hana::find_if(xs, hana::always(true_c)),
  99. hana::just(hana::front(xs))
  100. ));
  101. })(xs)
  102. );
  103. });
  104. }
  105. };
  106. template <typename S>
  107. struct TestIterable<S, when<Sequence<S>::value>>
  108. : TestIterable<S, laws>
  109. {
  110. template <int i>
  111. using x = ct_eq<i>;
  112. template <int i = 0>
  113. struct invalid { };
  114. struct undefined { };
  115. template <typename Xs>
  116. TestIterable(Xs xs) : TestIterable<S, laws>{xs} {
  117. constexpr auto list = make<S>;
  118. //////////////////////////////////////////////////////////////////
  119. // front
  120. //////////////////////////////////////////////////////////////////
  121. BOOST_HANA_CONSTANT_CHECK(equal(
  122. front(list(x<0>{})),
  123. x<0>{}
  124. ));
  125. BOOST_HANA_CONSTANT_CHECK(equal(
  126. front(list(x<0>{}, invalid<>{})),
  127. x<0>{}
  128. ));
  129. BOOST_HANA_CONSTANT_CHECK(equal(
  130. front(list(x<0>{}, invalid<1>{}, invalid<2>{})),
  131. x<0>{}
  132. ));
  133. BOOST_HANA_CONSTEXPR_CHECK(equal(
  134. front(list(1)), 1
  135. ));
  136. BOOST_HANA_CONSTEXPR_CHECK(equal(
  137. front(list(1, '2')), 1
  138. ));
  139. BOOST_HANA_CONSTEXPR_CHECK(equal(
  140. front(list(1, '2', 3.3)), 1
  141. ));
  142. //////////////////////////////////////////////////////////////////
  143. // back
  144. //////////////////////////////////////////////////////////////////
  145. BOOST_HANA_CONSTANT_CHECK(equal(
  146. back(list(x<0>{})),
  147. x<0>{}
  148. ));
  149. BOOST_HANA_CONSTANT_CHECK(equal(
  150. back(list(invalid<0>{}, x<1>{})),
  151. x<1>{}
  152. ));
  153. BOOST_HANA_CONSTANT_CHECK(equal(
  154. back(list(invalid<0>{}, invalid<1>{}, x<2>{})),
  155. x<2>{}
  156. ));
  157. BOOST_HANA_CONSTEXPR_CHECK(equal(
  158. back(list(1)), 1
  159. ));
  160. BOOST_HANA_CONSTEXPR_CHECK(equal(
  161. back(list(1, '2')), '2'
  162. ));
  163. BOOST_HANA_CONSTEXPR_CHECK(equal(
  164. back(list(1, '2', 3.3)), 3.3
  165. ));
  166. }
  167. };
  168. }}} // end namespace boost::hana::test
  169. #endif // !BOOST_HANA_TEST_LAWS_ITERABLE_HPP