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_MONOID_HPP
6 #define BOOST_HANA_TEST_LAWS_MONOID_HPP
7 
8 #include <boost/hana/assert.hpp>
9 #include <boost/hana/bool.hpp>
10 #include <boost/hana/concept/comparable.hpp>
11 #include <boost/hana/core/when.hpp>
12 #include <boost/hana/functional/capture.hpp>
13 #include <boost/hana/lazy.hpp>
14 #include <boost/hana/concept/monoid.hpp>
15 
16 #include <laws/base.hpp>
17 
18 
19 namespace boost { namespace hana { namespace test {
20     template <typename M, typename = when<true>>
21     struct TestMonoid : TestMonoid<M, laws> {
22         using TestMonoid<M, laws>::TestMonoid;
23     };
24 
25     template <typename M>
26     struct TestMonoid<M, laws> {
27         template <typename Xs>
TestMonoidboost::hana::test::TestMonoid28         TestMonoid(Xs xs) {
29 #ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
30             zero<M>(); // force adding zero<M>'s member function to pending temploid list
31 #endif
32 
33             hana::for_each(xs, hana::capture(xs)([](auto xs, auto a) {
34                 static_assert(Monoid<decltype(a)>{}, "");
35 
36                 // left identity
37                 BOOST_HANA_CHECK(hana::equal(
38                     hana::plus(zero<M>(), a),
39                     a
40                 ));
41 
42                 // right identity
43                 BOOST_HANA_CHECK(hana::equal(
44                     hana::plus(a, zero<M>()),
45                     a
46                 ));
47 
48                 hana::for_each(xs,
49                 hana::capture(xs, a)([](auto xs, auto a, auto b) {
50                     hana::for_each(xs,
51                     hana::capture(a, b)([](auto a, auto b, auto c) {
52                         // associativity
53                         BOOST_HANA_CHECK(equal(
54                             hana::plus(a, hana::plus(b, c)),
55                             hana::plus(hana::plus(a, b), c)
56                         ));
57                     }));
58                 }));
59 
60             }));
61         }
62     };
63 
64     template <typename C>
65     struct TestMonoid<C, when<Constant<C>::value>>
66         : TestMonoid<C, laws>
67     {
68         template <typename Xs>
TestMonoidboost::hana::test::TestMonoid69         TestMonoid(Xs xs) : TestMonoid<C, laws>{xs} {
70 
71             BOOST_HANA_CHECK(hana::equal(
72                 hana::value(zero<C>()),
73                 zero<typename C::value_type>()
74             ));
75 
__anon73f567a50402boost::hana::test::TestMonoid76             foreach2(xs, [](auto x, auto y) {
77                 BOOST_HANA_CHECK(hana::equal(
78                     hana::plus(hana::value(x), hana::value(y)),
79                     hana::value(hana::plus(x, y))
80                 ));
81             });
82         }
83     };
84 }}} // end namespace boost::hana::test
85 
86 #endif // !BOOST_HANA_TEST_LAWS_MONOID_HPP
87