// Copyright Louis Dionne 2013-2017 // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) #ifndef BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP #define BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace hana { namespace test { template > struct TestMonadPlus : TestMonadPlus { using TestMonadPlus::TestMonadPlus; }; template struct TestMonadPlus { template TestMonadPlus(Xs xs, Predicates predicates, Values values) { #ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735 empty(); // force adding empty's member function to pending temploid list #endif hana::for_each(xs, [](auto a) { static_assert(MonadPlus{}, ""); // left identity BOOST_HANA_CHECK(hana::equal( hana::concat(hana::empty(), a), a )); // right identity BOOST_HANA_CHECK(hana::equal( hana::concat(a, hana::empty()), a )); // absorption auto f = hana::compose(lift, test::_injection<0>{}); BOOST_HANA_CHECK(hana::equal( hana::chain(hana::empty(), f), hana::empty() )); BOOST_HANA_CHECK(hana::equal( hana::chain(a, hana::always(hana::empty())), hana::empty() )); }); // associativity foreach3(xs, [](auto a, auto b, auto c) { BOOST_HANA_CHECK(hana::equal( hana::concat(a, hana::concat(b, c)), hana::concat(hana::concat(a, b), c) )); }); // Default method definitions hana::for_each(xs, hana::capture(predicates, values)( [](auto predicates, auto values, auto x) { // remove_if(x, pred) == filter(x, negated pred) hana::for_each(predicates, hana::capture(x)([](auto x, auto pred) { BOOST_HANA_CHECK(hana::equal( hana::remove_if(x, pred), hana::filter(x, hana::compose(hana::not_, pred)) )); })); // remove(x, value) == remove_if(x, equal.to(value)) hana::for_each(values, hana::capture(x)([](auto x, auto value) { BOOST_HANA_CHECK(hana::equal( hana::remove(x, value), hana::remove_if(x, hana::equal.to(value)) )); })); })); } }; template struct TestMonadPlus::value>> : TestMonadPlus { template using eq = test::ct_eq; struct undefined { }; template TestMonadPlus(Xs xs, Predicates predicates, Values values) : TestMonadPlus{xs, predicates, values} { auto z = eq<999>{}; constexpr auto list = make; ////////////////////////////////////////////////////////////////// // empty ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( hana::empty(), list() )); ////////////////////////////////////////////////////////////////// // concat ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( concat(list(), list()), list() )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(), list(eq<0>{})), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(), list(eq<0>{}, eq<1>{})), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(eq<0>{}), list()), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(eq<0>{}), list(eq<1>{})), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(eq<0>{}), list(eq<1>{}, eq<2>{})), list(eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(eq<0>{}, eq<1>{}), list()), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(eq<0>{}, eq<1>{}), list(eq<2>{})), list(eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(eq<0>{}, eq<1>{}), list(eq<2>{}, eq<3>{})), list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( concat(list(), list()), list() )); BOOST_HANA_CONSTEXPR_CHECK(equal( concat(list(1), list()), list(1) )); BOOST_HANA_CONSTEXPR_CHECK(equal( concat(list(), list(1)), list(1) )); BOOST_HANA_CONSTEXPR_CHECK(equal( concat(list(1), list('2')), list(1, '2') )); BOOST_HANA_CONSTEXPR_CHECK(equal( concat(list(1, '2'), list(3.3)), list(1, '2', 3.3) )); ////////////////////////////////////////////////////////////////// // filter ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( filter(list(), undefined{}), list() )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(z), not_equal.to(z)), list() )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(eq<1>{}), not_equal.to(z)), list(eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(eq<1>{}, eq<2>{}), not_equal.to(z)), list(eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(z, eq<2>{}), not_equal.to(z)), list(eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(eq<1>{}, z), not_equal.to(z)), list(eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(z, eq<2>{}, eq<3>{}), not_equal.to(z)), list(eq<2>{}, eq<3>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(eq<1>{}, z, eq<3>{}), not_equal.to(z)), list(eq<1>{}, eq<3>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(eq<1>{}, eq<2>{}, z), not_equal.to(z)), list(eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(eq<1>{}, z, z), not_equal.to(z)), list(eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(z, eq<2>{}, z), not_equal.to(z)), list(eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(z, z, eq<3>{}), not_equal.to(z)), list(eq<3>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( filter(list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}, z), not_equal.to(z)), list(eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}) )); ////////////////////////////////////////////////////////////////// // prepend ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( prepend(list(), eq<0>{}), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( prepend(list(eq<1>{}), eq<0>{}), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( prepend(list(eq<1>{}, eq<2>{}), eq<0>{}), list(eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( prepend(list(eq<1>{}, eq<2>{}, eq<3>{}), eq<0>{}), list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}) )); BOOST_HANA_CONSTEXPR_CHECK(equal( prepend(list(), 1), list(1) )); BOOST_HANA_CONSTEXPR_CHECK(equal( prepend(list('2'), 1), list(1, '2') )); BOOST_HANA_CONSTEXPR_CHECK(equal( prepend(list('2', 3.3), 1), list(1, '2', 3.3) )); ////////////////////////////////////////////////////////////////// // append ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( append(list(), eq<0>{}), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( append(list(eq<0>{}), eq<1>{}), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( append(list(eq<0>{}, eq<1>{}), eq<2>{}), list(eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTEXPR_CHECK(equal( append(list(), 1), list(1) )); BOOST_HANA_CONSTEXPR_CHECK(equal( append(list(1), '2'), list(1, '2') )); BOOST_HANA_CONSTEXPR_CHECK(equal( append(list(1, '2'), 3.3), list(1, '2', 3.3) )); ////////////////////////////////////////////////////////////////// // cycle ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(), size_c<0>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(), size_c<1>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(), size_c<2>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(), size_c<3>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}), size_c<0>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}), size_c<1>), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}), size_c<2>), list(eq<0>{}, eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}), size_c<3>), list(eq<0>{}, eq<0>{}, eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}), size_c<0>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}), size_c<1>), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}), size_c<2>), list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}), size_c<3>), list(eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{}, eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<0>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<1>), list(eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<2>), list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( cycle(list(eq<0>{}, eq<1>{}, eq<2>{}), size_c<3>), list(eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{}, eq<0>{}, eq<1>{}, eq<2>{}) )); ////////////////////////////////////////////////////////////////// // remove_if ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(), undefined{}), list() )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(eq<0>{}), equal.to(z)), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(z), equal.to(z)), list() )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(eq<0>{}, eq<1>{}), equal.to(z)), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(z, eq<1>{}), equal.to(z)), list(eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(eq<0>{}, z), equal.to(z)), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(z, z), equal.to(z)), list() )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(eq<0>{}, eq<1>{}, eq<2>{}), equal.to(z)), list(eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(eq<0>{}, eq<1>{}, z), equal.to(z)), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(eq<0>{}, z, eq<2>{}), equal.to(z)), list(eq<0>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(z, eq<1>{}, eq<2>{}), equal.to(z)), list(eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(z, z, eq<2>{}), equal.to(z)), list(eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(eq<0>{}, z, z), equal.to(z)), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( remove_if(list(z, z, z), equal.to(z)), list() )); ////////////////////////////////////////////////////////////////// // remove ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(), undefined{}), list() )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(eq<0>{}), z), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(z), z), list() )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(eq<0>{}, eq<1>{}), z), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(z, eq<1>{}), z), list(eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(eq<0>{}, z), z), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(z, z), z), list() )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(eq<0>{}, eq<1>{}, eq<2>{}), z), list(eq<0>{}, eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(eq<0>{}, eq<1>{}, z), z), list(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(eq<0>{}, z, eq<2>{}), z), list(eq<0>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(z, eq<1>{}, eq<2>{}), z), list(eq<1>{}, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(z, z, eq<2>{}), z), list(eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(eq<0>{}, z, z), z), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( hana::remove(list(z, z, z), z), list() )); ////////////////////////////////////////////////////////////////// // replicate ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( replicate(eq<0>{}, size_c<0>), list() )); BOOST_HANA_CONSTANT_CHECK(equal( replicate(eq<0>{}, size_c<1>), list(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( replicate(eq<0>{}, size_c<2>), list(eq<0>{}, eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( replicate(eq<0>{}, size_c<3>), list(eq<0>{}, eq<0>{}, eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( replicate(eq<0>{}, size_c<4>), list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( replicate(eq<0>{}, size_c<5>), list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}) )); ////////////////////////////////////////////////////////////////// // prefix ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( prefix(list(), z), list() )); BOOST_HANA_CONSTANT_CHECK(equal( prefix(list(eq<0>{}), z), list(z, eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( prefix(list(eq<0>{}, eq<1>{}), z), list(z, eq<0>{}, z, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( prefix(list(eq<0>{}, eq<1>{}, eq<2>{}), z), list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( prefix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z), list(z, eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{}) )); ////////////////////////////////////////////////////////////////// // suffix ////////////////////////////////////////////////////////////////// BOOST_HANA_CONSTANT_CHECK(equal( suffix(list(), z), list() )); BOOST_HANA_CONSTANT_CHECK(equal( suffix(list(eq<0>{}), z), list(eq<0>{}, z) )); BOOST_HANA_CONSTANT_CHECK(equal( suffix(list(eq<0>{}, eq<1>{}), z), list(eq<0>{}, z, eq<1>{}, z) )); BOOST_HANA_CONSTANT_CHECK(equal( suffix(list(eq<0>{}, eq<1>{}, eq<2>{}), z), list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z) )); BOOST_HANA_CONSTANT_CHECK(equal( suffix(list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), z), list(eq<0>{}, z, eq<1>{}, z, eq<2>{}, z, eq<3>{}, z) )); } }; }}} // end namespace boost::hana::test #endif // !BOOST_HANA_TEST_LAWS_MONAD_PLUS_HPP