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 5 #ifndef BOOST_HANA_TEST_LAWS_COMPARABLE_HPP 6 #define BOOST_HANA_TEST_LAWS_COMPARABLE_HPP 7 8 #include <boost/hana/and.hpp> 9 #include <boost/hana/assert.hpp> 10 #include <boost/hana/bool.hpp> 11 #include <boost/hana/comparing.hpp> 12 #include <boost/hana/concept/comparable.hpp> 13 #include <boost/hana/concept/constant.hpp> 14 #include <boost/hana/concept/product.hpp> 15 #include <boost/hana/concept/sequence.hpp> 16 #include <boost/hana/core/make.hpp> 17 #include <boost/hana/core/when.hpp> 18 #include <boost/hana/equal.hpp> 19 #include <boost/hana/first.hpp> 20 #include <boost/hana/for_each.hpp> 21 #include <boost/hana/lazy.hpp> 22 #include <boost/hana/not_equal.hpp> 23 #include <boost/hana/second.hpp> 24 #include <boost/hana/value.hpp> 25 26 27 #include <laws/base.hpp> 28 29 30 namespace boost { namespace hana { namespace test { 31 template <typename T, typename = hana::when<true>> 32 struct TestComparable : TestComparable<T, laws> { 33 using TestComparable<T, laws>::TestComparable; 34 }; 35 36 template <typename T> 37 struct TestComparable<T, laws> { 38 template <typename Xs> TestComparableboost::hana::test::TestComparable39 TestComparable(Xs xs) { 40 hana::for_each(xs, [](auto x) { 41 static_assert(hana::Comparable<decltype(x)>{}, ""); 42 }); 43 44 foreach2(xs, [](auto a, auto b) { 45 46 // reflexivity 47 BOOST_HANA_CHECK( 48 hana::equal(a, a) 49 ); 50 51 // symmetry 52 BOOST_HANA_CHECK( 53 hana::equal(a, b) ^implies^ hana::equal(b, a) 54 ); 55 56 // `not_equal` is the negation of `equal` 57 BOOST_HANA_CHECK( 58 hana::not_equal(a, b) ^iff^ hana::not_(hana::equal(a, b)) 59 ); 60 61 // equal.to and not_equal.to 62 BOOST_HANA_CHECK( 63 hana::equal.to(a)(b) ^iff^ hana::equal(a, b) 64 ); 65 66 BOOST_HANA_CHECK( 67 hana::not_equal.to(a)(b) ^iff^ hana::not_equal(a, b) 68 ); 69 70 // comparing 71 _injection<0> f{}; 72 BOOST_HANA_CHECK( 73 hana::comparing(f)(a, b) ^iff^ hana::equal(f(a), f(b)) 74 ); 75 }); 76 77 // transitivity 78 foreach3(xs, [](auto a, auto b, auto c) { 79 BOOST_HANA_CHECK( 80 hana::and_(hana::equal(a, b), hana::equal(b, c)) 81 ^implies^ hana::equal(a, c) 82 ); 83 }); 84 } 85 }; 86 87 template <typename C> 88 struct TestComparable<C, when<Constant<C>::value>> 89 : TestComparable<C, laws> 90 { 91 template <typename Xs> TestComparableboost::hana::test::TestComparable92 TestComparable(Xs xs) : TestComparable<C, laws>{xs} { __anon359abdb50402boost::hana::test::TestComparable93 foreach2(xs, [](auto a, auto b) { 94 BOOST_HANA_CHECK( 95 hana::value(hana::equal(a, b)) ^iff^ 96 hana::equal(hana::value(a), hana::value(b)) 97 ); 98 }); 99 } 100 }; 101 102 template <typename P> 103 struct TestComparable<P, when<Product<P>::value>> 104 : TestComparable<P, laws> 105 { 106 template <typename Products> TestComparableboost::hana::test::TestComparable107 TestComparable(Products products) : TestComparable<P, laws>{products} { __anon359abdb50502boost::hana::test::TestComparable108 foreach2(products, [](auto x, auto y) { 109 BOOST_HANA_CHECK( 110 hana::equal(x, y) ^iff^ 111 hana::and_( 112 hana::equal(hana::first(x), hana::first(y)), 113 hana::equal(hana::second(x), hana::second(y)) 114 ) 115 ); 116 }); 117 } 118 }; 119 120 template <typename S> 121 struct TestComparable<S, when<Sequence<S>::value>> 122 : TestComparable<S, laws> 123 { 124 template <int i> 125 using x = _constant<i>; 126 127 template <typename Xs> TestComparableboost::hana::test::TestComparable128 TestComparable(Xs xs) : TestComparable<S, laws>{xs} { 129 constexpr auto list = make<S>; 130 131 ////////////////////////////////////////////////////////////////// 132 // equal 133 ////////////////////////////////////////////////////////////////// 134 BOOST_HANA_CONSTANT_CHECK(hana::equal( 135 list(), 136 list() 137 )); 138 BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( 139 list(x<0>{}), 140 list() 141 ))); 142 BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( 143 list(), 144 list(x<0>{}) 145 ))); 146 BOOST_HANA_CONSTANT_CHECK(hana::equal( 147 list(x<0>{}), 148 list(x<0>{}) 149 )); 150 151 BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( 152 list(x<0>{}, x<1>{}), 153 list(x<0>{}) 154 ))); 155 BOOST_HANA_CONSTANT_CHECK(hana::equal( 156 list(x<0>{}, x<1>{}), 157 list(x<0>{}, x<1>{}) 158 )); 159 BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( 160 list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), 161 list(x<0>{}, x<1>{}, x<2>{}, x<4>{}) 162 ))); 163 } 164 }; 165 }}} // end namespace boost::hana::test 166 167 #endif // !BOOST_HANA_TEST_LAWS_COMPARABLE_HPP 168