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_LOGICAL_HPP 6 #define BOOST_HANA_TEST_LAWS_LOGICAL_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/logical.hpp> 15 16 #include <laws/base.hpp> 17 18 19 namespace boost { namespace hana { namespace test { 20 template <typename L, typename = when<true>> 21 struct TestLogical : TestLogical<L, laws> { 22 using TestLogical<L, laws>::TestLogical; 23 }; 24 25 template <typename L> 26 struct TestLogical<L, laws> { 27 template <typename Xs, typename Pred, typename F> for_each_such_thatboost::hana::test::TestLogical28 static void for_each_such_that(Xs xs, Pred pred, F f) { 29 hana::for_each(xs, [&pred, &f](auto x) { 30 hana::eval_if(pred(x), 31 hana::make_lazy(f)(x), 32 [](auto) { } 33 ); 34 }); 35 } 36 37 template <typename Xs> TestLogicalboost::hana::test::TestLogical38 TestLogical(Xs xs) { 39 hana::for_each(xs, [](auto x) { 40 static_assert(Logical<decltype(x)>{}, ""); 41 }); 42 43 foreach3(xs, hana::capture(xs)([](auto xs, auto a, auto b, auto c) { 44 auto true_valued = [](auto x) { 45 return hana::if_(x, true_c, false_c); 46 }; 47 auto false_valued = [](auto x) { 48 return hana::if_(x, false_c, true_c); 49 }; 50 51 // associativity 52 BOOST_HANA_CHECK(hana::equal( 53 hana::or_(a, hana::or_(b, c)), 54 hana::or_(hana::or_(a, b), c) 55 )); 56 BOOST_HANA_CHECK(hana::equal( 57 hana::and_(a, hana::and_(b, c)), 58 hana::and_(hana::and_(a, b), c) 59 )); 60 61 // equivalence through commutativity 62 BOOST_HANA_CHECK( 63 hana::or_(a, b) ^iff^ hana::or_(b, a) 64 ); 65 BOOST_HANA_CHECK( 66 hana::and_(a, b) ^iff^ hana::and_(b, a) 67 ); 68 69 // absorption 70 BOOST_HANA_CHECK(hana::equal( 71 hana::or_(a, hana::and_(a, b)), a 72 )); 73 BOOST_HANA_CHECK(hana::equal( 74 hana::and_(a, hana::or_(a, b)), a 75 )); 76 77 // left identity 78 TestLogical::for_each_such_that(xs, true_valued, 79 hana::capture(a)([](auto a, auto t) { 80 BOOST_HANA_CHECK(hana::equal( 81 hana::and_(t, a), a 82 )); 83 })); 84 TestLogical::for_each_such_that(xs, false_valued, 85 hana::capture(a)([](auto a, auto f) { 86 BOOST_HANA_CHECK(hana::equal( 87 hana::or_(f, a), a 88 )); 89 })); 90 91 // distributivity 92 BOOST_HANA_CHECK(hana::equal( 93 hana::or_(a, hana::and_(b, c)), 94 hana::and_(hana::or_(a, b), hana::or_(a, c)) 95 )); 96 BOOST_HANA_CHECK(hana::equal( 97 hana::and_(a, hana::or_(b, c)), 98 hana::or_(hana::and_(a, b), hana::and_(a, c)) 99 )); 100 101 // complements 102 BOOST_HANA_CHECK(true_valued(hana::or_(a, hana::not_(a)))); 103 BOOST_HANA_CHECK(false_valued(hana::and_(a, hana::not_(a)))); 104 105 })); 106 } 107 }; 108 109 template <typename C> 110 struct TestLogical<C, when<Constant<C>::value>> 111 : TestLogical<C, laws> 112 { 113 template <typename Xs> TestLogicalboost::hana::test::TestLogical114 TestLogical(Xs xs) : TestLogical<C, laws>{xs} { __anone83a8cb00902boost::hana::test::TestLogical115 foreach2(xs, [](auto x, auto y) { 116 117 BOOST_HANA_CHECK(hana::equal( 118 hana::value(hana::not_(x)), 119 hana::not_(hana::value(x)) 120 )); 121 122 BOOST_HANA_CHECK(hana::equal( 123 hana::value(hana::and_(x, y)), 124 hana::and_(hana::value(x), hana::value(y)) 125 )); 126 127 BOOST_HANA_CHECK(hana::equal( 128 hana::value(hana::or_(x, y)), 129 hana::or_(hana::value(x), hana::value(y)) 130 )); 131 132 }); 133 } 134 }; 135 }}} // end namespace boost::hana::test 136 137 #endif // !BOOST_HANA_TEST_LAWS_LOGICAL_HPP 138