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