orderable.hpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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_ORDERABLE_HPP
  5. #define BOOST_HANA_TEST_LAWS_ORDERABLE_HPP
  6. #include <boost/hana/and.hpp>
  7. #include <boost/hana/assert.hpp>
  8. #include <boost/hana/bool.hpp>
  9. #include <boost/hana/concept/constant.hpp>
  10. #include <boost/hana/concept/orderable.hpp>
  11. #include <boost/hana/concept/product.hpp>
  12. #include <boost/hana/concept/sequence.hpp>
  13. #include <boost/hana/core/when.hpp>
  14. #include <boost/hana/first.hpp>
  15. #include <boost/hana/greater.hpp>
  16. #include <boost/hana/greater_equal.hpp>
  17. #include <boost/hana/lazy.hpp>
  18. #include <boost/hana/less.hpp>
  19. #include <boost/hana/less_equal.hpp>
  20. #include <boost/hana/not.hpp>
  21. #include <boost/hana/or.hpp>
  22. #include <boost/hana/ordering.hpp>
  23. #include <boost/hana/second.hpp>
  24. #include <boost/hana/value.hpp>
  25. #include <laws/base.hpp>
  26. namespace boost { namespace hana { namespace test {
  27. template <typename T, typename = when<true>>
  28. struct TestOrderable : TestOrderable<T, laws> {
  29. using TestOrderable<T, laws>::TestOrderable;
  30. };
  31. template <typename T>
  32. struct TestOrderable<T, laws> {
  33. template <typename Xs>
  34. TestOrderable(Xs xs) {
  35. hana::for_each(xs, [](auto x) {
  36. static_assert(Orderable<decltype(x)>{}, "");
  37. });
  38. foreach2(xs, [](auto a, auto b) {
  39. // antisymmetry
  40. BOOST_HANA_CHECK(
  41. hana::and_(hana::less_equal(a, b), hana::less_equal(b, a))
  42. ^implies^ hana::equal(a, b)
  43. );
  44. // totality
  45. BOOST_HANA_CHECK(
  46. hana::or_(hana::less_equal(a, b), hana::less_equal(b, a))
  47. );
  48. // other methods in terms of `less_equal`
  49. BOOST_HANA_CHECK(
  50. hana::less(a, b) ^iff^ hana::not_(hana::less_equal(b, a))
  51. );
  52. BOOST_HANA_CHECK(
  53. hana::greater(a, b) ^iff^ hana::less(b, a)
  54. );
  55. BOOST_HANA_CHECK(
  56. hana::greater_equal(a, b) ^iff^ hana::not_(hana::less(a, b))
  57. );
  58. // less.than & al.
  59. BOOST_HANA_CHECK(hana::less.than(a)(b) ^iff^ hana::less(b, a));
  60. BOOST_HANA_CHECK(hana::greater.than(a)(b) ^iff^ hana::greater(b, a));
  61. BOOST_HANA_CHECK(hana::less_equal.than(a)(b) ^iff^ hana::less_equal(b, a));
  62. BOOST_HANA_CHECK(hana::greater_equal.than(a)(b) ^iff^ hana::greater_equal(b, a));
  63. // ordering
  64. _injection<0> f{}; // test::_injection is also monotonic
  65. BOOST_HANA_CHECK(
  66. hana::ordering(f)(a, b) ^iff^ hana::less(f(a), f(b))
  67. );
  68. });
  69. // transitivity
  70. foreach3(xs, [](auto a, auto b, auto c) {
  71. BOOST_HANA_CHECK(
  72. hana::and_(hana::less_equal(a, b), hana::less_equal(b, c))
  73. ^implies^ hana::less_equal(a, c)
  74. );
  75. });
  76. }
  77. };
  78. template <typename C>
  79. struct TestOrderable<C, when<Constant<C>::value>>
  80. : TestOrderable<C, laws>
  81. {
  82. template <typename Xs>
  83. TestOrderable(Xs xs) : TestOrderable<C, laws>{xs} {
  84. foreach2(xs, [](auto a, auto b) {
  85. BOOST_HANA_CHECK(
  86. hana::value(hana::less(a, b)) ^iff^
  87. hana::less(hana::value(a), hana::value(b))
  88. );
  89. });
  90. }
  91. };
  92. template <typename P>
  93. struct TestOrderable<P, when<Product<P>::value>>
  94. : TestOrderable<P, laws>
  95. {
  96. template <typename Products>
  97. TestOrderable(Products products)
  98. : TestOrderable<P, laws>{products}
  99. {
  100. foreach2(products, [](auto x, auto y) {
  101. BOOST_HANA_CHECK(
  102. hana::less(x, y) ^iff^
  103. hana::or_(
  104. hana::less(hana::first(x), hana::first(y)),
  105. hana::and_(
  106. hana::equal(hana::first(x), hana::first(y)),
  107. hana::less(hana::second(x), hana::second(y))
  108. )
  109. )
  110. );
  111. });
  112. }
  113. };
  114. template <typename S>
  115. struct TestOrderable<S, when<Sequence<S>::value>>
  116. : TestOrderable<S, laws>
  117. {
  118. struct invalid { };
  119. template <typename Xs>
  120. TestOrderable(Xs xs) : TestOrderable<S, laws>{xs} {
  121. constexpr auto list = make<S>;
  122. //////////////////////////////////////////////////////////////////
  123. // less
  124. //////////////////////////////////////////////////////////////////
  125. BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
  126. list(),
  127. list()
  128. )));
  129. BOOST_HANA_CONSTANT_CHECK(hana::less(
  130. list(),
  131. list(invalid{})
  132. ));
  133. BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
  134. list(invalid{}),
  135. list()
  136. )));
  137. BOOST_HANA_CONSTANT_CHECK(hana::less(
  138. list(ct_ord<0>{}),
  139. list(ct_ord<7>{})
  140. ));
  141. BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
  142. list(ct_ord<1>{}),
  143. list(ct_ord<0>{})
  144. )));
  145. BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less(
  146. list(ct_ord<0>{}, ct_ord<1>{}, ct_ord<8>{}),
  147. list(ct_ord<0>{}, ct_ord<1>{})
  148. )));
  149. BOOST_HANA_CONSTANT_CHECK(hana::less(
  150. list(ct_ord<0>{}, ct_ord<0>{}, ct_ord<8>{}),
  151. list(ct_ord<0>{}, ct_ord<1>{})
  152. ));
  153. }
  154. };
  155. }}} // end namespace boost::hana::test
  156. #endif // !BOOST_HANA_TEST_LAWS_ORDERABLE_HPP