diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/hana/test/_include/laws | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/hana/test/_include/laws')
21 files changed, 4982 insertions, 0 deletions
diff --git a/src/boost/libs/hana/test/_include/laws/applicative.hpp b/src/boost/libs/hana/test/_include/laws/applicative.hpp new file mode 100644 index 000000000..a7de47b9d --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/applicative.hpp @@ -0,0 +1,196 @@ +// 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_APPLICATIVE_HPP +#define BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP + +#include <boost/hana/ap.hpp> +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/applicative.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/functional/compose.hpp> +#include <boost/hana/functional/curry.hpp> +#include <boost/hana/functional/id.hpp> +#include <boost/hana/functional/placeholder.hpp> +#include <boost/hana/integral_constant.hpp> +#include <boost/hana/lift.hpp> +#include <boost/hana/take_front.hpp> +#include <boost/hana/transform.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename F, typename = when<true>> + struct TestApplicative : TestApplicative<F, laws> { + using TestApplicative<F, laws>::TestApplicative; + }; + + template <typename F> + struct TestApplicative<F, laws> { + template <typename Applicatives> + TestApplicative(Applicatives applicatives) { + hana::for_each(applicatives, [](auto a) { + static_assert(Applicative<decltype(a)>{}, ""); + }); + + auto functions1 = hana::take_front( + hana::transform(applicatives, [](auto xs) { + return hana::transform(xs, hana::curry<2>(test::_injection<0>{})); + }), hana::int_c<3>); + + auto functions2 = hana::take_front( + hana::transform(applicatives, [](auto xs) { + return hana::transform(xs, hana::curry<2>(test::_injection<1>{})); + }), hana::int_c<3>); + + // identity + { + hana::for_each(applicatives, [](auto xs) { + BOOST_HANA_CHECK(hana::equal( + hana::ap(hana::lift<F>(hana::id), xs), + xs + )); + }); + } + + // composition + { + hana::for_each(applicatives, hana::capture(functions1, functions2)( + [](auto functions1, auto functions2, auto xs) { + hana::for_each(functions1, hana::capture(functions2, xs)( + [](auto functions2, auto xs, auto fs) { + hana::for_each(functions2, hana::capture(xs, fs)( + [](auto xs, auto fs, auto gs) { + BOOST_HANA_CHECK(hana::equal( + hana::ap(hana::ap(hana::lift<F>(compose), fs, gs), xs), + hana::ap(fs, hana::ap(gs, xs)) + )); + }));}));})); + } + + // homomorphism + { + test::_injection<0> f{}; + test::ct_eq<3> x{}; + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(hana::lift<F>(f), hana::lift<F>(x)), + hana::lift<F>(f(x)) + )); + } + + // interchange + { + hana::for_each(functions1, [](auto fs) { + test::ct_eq<4> x{}; + BOOST_HANA_CHECK(hana::equal( + hana::ap(fs, hana::lift<F>(x)), + hana::ap(hana::lift<F>(hana::_(x)), fs) + )); + }); + } + + // definition of transform + { + hana::for_each(applicatives, [](auto xs) { + test::_injection<0> f{}; + BOOST_HANA_CHECK(hana::equal( + hana::transform(xs, f), + hana::ap(hana::lift<F>(f), xs) + )); + }); + } + } + }; + + template <typename S> + struct TestApplicative<S, when<Sequence<S>::value>> + : TestApplicative<S, laws> + { + template <typename Applicatives> + TestApplicative(Applicatives applicatives) + : TestApplicative<S, laws>{applicatives} + { + _injection<0> f{}; + _injection<1> g{}; + using test::ct_eq; + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // ap + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(), list()), + list() + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(), list(ct_eq<0>{})), + list() + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(), list(ct_eq<0>{}, ct_eq<1>{})), + list() + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f), list()), + list() + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f), list(ct_eq<0>{})), + list(f(ct_eq<0>{})) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f), list(ct_eq<0>{}, ct_eq<1>{})), + list(f(ct_eq<0>{}), f(ct_eq<1>{})) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})), + list(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f, g), list()), + list() + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f, g), list(ct_eq<0>{})), + list(f(ct_eq<0>{}), g(ct_eq<0>{})) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f, g), list(ct_eq<0>{}, ct_eq<1>{})), + list(f(ct_eq<0>{}), f(ct_eq<1>{}), g(ct_eq<0>{}), g(ct_eq<1>{})) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::ap(list(f, g), list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{})), + list(f(ct_eq<0>{}), f(ct_eq<1>{}), f(ct_eq<2>{}), + g(ct_eq<0>{}), g(ct_eq<1>{}), g(ct_eq<2>{})) + )); + + ////////////////////////////////////////////////////////////////// + // lift + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(hana::equal( + lift<S>(ct_eq<0>{}), + list(ct_eq<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + lift<S>(ct_eq<1>{}), + list(ct_eq<1>{}) + )); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_APPLICATIVE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/base.hpp b/src/boost/libs/hana/test/_include/laws/base.hpp new file mode 100644 index 000000000..0f421b8ae --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/base.hpp @@ -0,0 +1,369 @@ +// 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_BASE_HPP +#define BOOST_HANA_TEST_LAWS_BASE_HPP + +#include <boost/hana/and.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/detail/wrong.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/eval_if.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/functional/compose.hpp> +#include <boost/hana/functional/infix.hpp> +#include <boost/hana/functional/partial.hpp> +#include <boost/hana/fwd/concept/integral_constant.hpp> +#include <boost/hana/fwd/core/to.hpp> +#include <boost/hana/fwd/less.hpp> +#include <boost/hana/not.hpp> +#include <boost/hana/or.hpp> +#include <boost/hana/tuple.hpp> + +#include <support/tracked.hpp> + +#include <type_traits> +#include <utility> + + +namespace boost { namespace hana { + ////////////////////////////////////////////////////////////////////////// + // Misc + ////////////////////////////////////////////////////////////////////////// + namespace test { + struct laws; + + template <int i> + struct for_each_n_t { + static_assert(i > 0, "can't use for_each_n with i < 0"); + + template <typename Xs, typename F> + constexpr auto operator()(Xs const& xs, F const& f) const { + hana::for_each(xs, + hana::compose( + hana::partial(for_each_n_t<i - 1>{}, xs), + hana::partial(hana::partial, f) + ) + ); + } + }; + + template <> + struct for_each_n_t<1> { + template <typename Xs, typename F> + constexpr auto operator()(Xs const& xs, F const& f) const { + hana::for_each(xs, f); + } + }; + + template <int i> + constexpr for_each_n_t<i> for_each_n{}; + + auto foreach = hana::for_each; + constexpr auto foreach3 = for_each_n<3>; + constexpr auto foreach2 = for_each_n<2>; + + struct implies_t { + template <typename P, typename Q> + constexpr decltype(auto) operator()(P&& p, Q&& q) const { + return hana::or_(hana::not_(static_cast<P&&>(p)), + static_cast<Q&&>(q)); + } + }; + constexpr auto implies = hana::infix(implies_t{}); + + struct iff_t { + template <typename P, typename Q> + constexpr decltype(auto) operator()(P&& p, Q&& q) const { + return hana::and_(implies(p, q), implies(q, p)); + } + }; + constexpr auto iff = hana::infix(iff_t{}); + + template <typename Cond, typename F> + constexpr decltype(auto) only_when_(Cond cond, F f) { + return hana::eval_if(cond, f, [](auto){ }); + } + + // A type with a constructor that must not be instantiated. + // This is to make sure we don't instantiate something else than + // the copy-constructor of the elements inside a container when we + // copy the container. + struct trap_construct { + trap_construct() = default; + trap_construct(trap_construct const&) = default; +#ifndef BOOST_HANA_WORKAROUND_MSVC_MULTIPLECTOR_106654 + trap_construct(trap_construct&) = default; +#endif + trap_construct(trap_construct&&) = default; + + template <typename X> + trap_construct(X&&) { + static_assert(detail::wrong<X>{}, + "this constructor must not be instantiated"); + } + }; + + // A move-only type. Useful for testing containers. + struct move_only { + move_only() = default; + move_only(move_only const&) = delete; + move_only(move_only&&) = default; + }; + + ////////////////////////////////////////////////////////////////////// + // InjectionResult + ////////////////////////////////////////////////////////////////////// + struct InjectionResult { }; + + template <int i, typename ...X> + struct injection_result { + using hana_tag = InjectionResult; + static constexpr int injection_id = i; + hana::tuple<X...> args; + Tracked tracker; + + template <typename ...Y, typename = decltype(tuple<X...>{std::declval<Y>()...})> + constexpr explicit injection_result(Y&& ...y) + : args{static_cast<Y&&>(y)...}, tracker{i} + { } + }; + + //! A monotonic injective function. + //! + //! This is used in the unit tests, where we often just need a function + //! which preserves equality and order, but which also satisfies the + //! following law for all `Injection`s `f` and `g`: + //! @code + //! f(x) == g(x) if and only if f === g + //! @endcode + //! where `===` means _was created by the same call to `injection`_. + //! This allows creating several such functions in the unit tests while + //! conserving precious information such as the fact that + //! `f(g(x)) != g(f(x))`. + template <int i> + struct _injection { + template <typename ...X> + constexpr auto operator()(X&& ...x) const { + return injection_result<i, + typename std::decay<X>::type... + >{static_cast<X&&>(x)...}; + } + }; + } // end namespace test + + template <> + struct equal_impl<test::InjectionResult, test::InjectionResult> { + template <typename X, typename Y> + static constexpr auto apply(X x, Y y) { + return hana::and_( + hana::bool_c<X::injection_id == Y::injection_id>, + hana::equal(x.args, y.args) + ); + } + }; + + template <> + struct less_impl<test::InjectionResult, test::InjectionResult> { + template <typename X, typename Y> + static constexpr auto apply(X x, Y y) { + static_assert(X::injection_id == Y::injection_id, + "can't order the result of two different injections"); + return hana::less(x.args, y.args); + } + }; + + + ////////////////////////////////////////////////////////////////////////// + // Integer + ////////////////////////////////////////////////////////////////////////// + namespace test { + enum class Policy : int { + // One of those is mandatory + Constant = 1 << 0 + , Constexpr = 1 << 1 + , Runtime = 1 << 2 + + // Those are optional + , Tracked = 1 << 3 + , Comparable = 1 << 4 + , Orderable = 1 << 5 + }; + + constexpr bool operator&&(Policy a, Policy b) { + return static_cast<int>(a) && static_cast<int>(b); + } + + constexpr bool operator&&(Policy a, bool b) { + return static_cast<int>(a) && b; + } + + constexpr bool operator&&(bool a, Policy b) { + return a && static_cast<int>(b); + } + + constexpr bool operator||(Policy a, Policy b) { + return static_cast<int>(a) || static_cast<int>(b); + } + + constexpr bool operator||(Policy a, bool b) { + return static_cast<int>(a) || b; + } + + constexpr bool operator||(bool a, Policy b) { + return a || static_cast<int>(b); + } + + constexpr bool operator!(Policy a) { + return !static_cast<int>(a); + } + + constexpr Policy operator|(Policy a, Policy b) { + return static_cast<Policy>(static_cast<int>(a) | static_cast<int>(b)); + } + + constexpr Policy operator&(Policy a, Policy b) { + return static_cast<Policy>(static_cast<int>(a) & static_cast<int>(b)); + } + + template <Policy policy, typename = void> + struct Integer { }; + + template <Policy policy> + struct Integer<policy, std::enable_if_t<!!(policy & Policy::Constant)>> { + using value_type = int; + }; + + template <int i, Policy policy, typename = void> + struct integer { + static_assert( + !!(policy & (Policy::Constant | Policy::Constexpr | Policy::Runtime)) + , "You must choose at least one of Constant, Constexpr and Runtime."); + + static constexpr int value = i; + constexpr operator int() const { return value; } + using hana_tag = Integer<policy>; + Tracked tracker{i}; + }; + + template <int i, Policy policy> + struct integer <i, policy, std::enable_if_t<!!(policy & Policy::Constexpr)>> { + static constexpr int value = i; + constexpr operator int() const { return value; } + using hana_tag = Integer<policy>; + }; + + template <int i> + struct eq : integer<i, Policy::Comparable | Policy::Runtime> { }; + + template <int i> + struct ct_eq : integer<i, Policy::Comparable | Policy::Constant> { }; + + template <int i> + struct cx_eq : integer<i, Policy::Comparable | Policy::Constexpr> { }; + + template <int i> + struct ord : integer<i, Policy::Orderable | Policy::Runtime> { }; + + template <int i> + struct ct_ord : integer<i, Policy::Orderable | Policy::Constant> { }; + + template <int i> + struct cx_ord : integer<i, Policy::Orderable | Policy::Constexpr> { }; + + template <int i> + struct _constant + : integer<i, Policy::Constant | Policy::Comparable | Policy::Orderable> + { }; + } + + ////////////////////////////////////////////////////////////////////////// + // Model of Constant/IntegralConstant + ////////////////////////////////////////////////////////////////////////// + template <test::Policy policy> + struct IntegralConstant<test::Integer<policy>> { + static constexpr bool value = static_cast<bool>(policy & test::Policy::Constant); + }; + + template <test::Policy policy, typename C> + struct to_impl<test::Integer<policy>, C, when< + (policy & test::Policy::Constant) && + hana::IntegralConstant<C>::value + >> + : embedding<is_embedded<typename C::value_type, int>::value> + { + template <typename N> + static constexpr auto apply(N const&) { + return test::integer<N::value, policy>{}; + } + }; + + ////////////////////////////////////////////////////////////////////////// + // Model of Comparable + ////////////////////////////////////////////////////////////////////////// + template <test::Policy p1, test::Policy p2> + struct equal_impl<test::Integer<p1>, test::Integer<p2>, when< + // both Comparable or Orderable + (p1 & (test::Policy::Comparable | test::Policy::Orderable)) && + (p2 & (test::Policy::Comparable | test::Policy::Orderable)) && + + // one Constexpr and the other Constant, or both Constexpr + (((p1 & test::Policy::Constant) && (p2 & test::Policy::Constexpr)) || + ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constant)) || + ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constexpr))) + >> { + template <typename X, typename Y> + static constexpr bool apply(X const&, Y const&) + { return X::value == Y::value; } + }; + + template <test::Policy p1, test::Policy p2> + struct equal_impl<test::Integer<p1>, test::Integer<p2>, when< + // both Comparable or Orderable + (p1 & (test::Policy::Comparable | test::Policy::Orderable)) && + (p2 & (test::Policy::Comparable | test::Policy::Orderable)) && + + // either one is Runtime + ((p1 & test::Policy::Runtime) || (p2 & test::Policy::Runtime)) + >> { + template <typename X, typename Y> + static bool apply(X const&, Y const&) + { return X::value == Y::value; } + }; + + + ////////////////////////////////////////////////////////////////////////// + // Model of Orderable + ////////////////////////////////////////////////////////////////////////// + template <test::Policy p1, test::Policy p2> + struct less_impl<test::Integer<p1>, test::Integer<p2>, when< + // both Orderable + (p1 & test::Policy::Orderable) && (p2 & test::Policy::Orderable) && + + // one Constexpr and the other Constant, or both Constexpr + (((p1 & test::Policy::Constant) && (p2 & test::Policy::Constexpr)) || + ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constant)) || + ((p1 & test::Policy::Constexpr) && (p2 & test::Policy::Constexpr))) + >> { + template <typename X, typename Y> + static constexpr bool apply(X const&, Y const&) + { return X::value < Y::value; } + }; + + template <test::Policy p1, test::Policy p2> + struct less_impl<test::Integer<p1>, test::Integer<p2>, when< + // both Orderable + (p1 & test::Policy::Orderable) && (p2 & test::Policy::Orderable) && + + // either one is Runtime + ((p1 & test::Policy::Runtime) || (p2 & test::Policy::Runtime)) + >> { + template <typename X, typename Y> + static bool apply(X const&, Y const&) + { return X::value < Y::value; } + }; +}} // end namespace boost::hana + +#endif // !BOOST_HANA_TEST_LAWS_BASE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/comonad.hpp b/src/boost/libs/hana/test/_include/laws/comonad.hpp new file mode 100644 index 000000000..82ef7b32d --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/comonad.hpp @@ -0,0 +1,53 @@ +// 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_COMONAD_HPP +#define BOOST_HANA_TEST_LAWS_COMONAD_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/concept/comonad.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/concept/foldable.hpp> +#include <boost/hana/concept/functor.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename W, typename = when<true>> + struct TestComonad : TestComonad<W, laws> { + using TestComonad<W, laws>::TestComonad; + }; + + template <typename W> + struct TestComonad<W, laws> { + template <typename Ws> + TestComonad(Ws ws) { + hana::for_each(ws, [](auto w) { + static_assert(Comonad<decltype(w)>{}, ""); + + // extract(duplicate(w)) == w + BOOST_HANA_CHECK(hana::equal( + hana::extract(hana::duplicate(w)), + w + )); + + // transform(duplicate(w), extract) == w + BOOST_HANA_CHECK(hana::equal( + hana::transform(hana::duplicate(w), extract), + w + )); + + // duplicate(duplicate(w)) == transform(duplicate(w), duplicate) + BOOST_HANA_CHECK(hana::equal( + hana::duplicate(hana::duplicate(w)), + hana::transform(hana::duplicate(w), duplicate) + )); + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_COMONAD_HPP diff --git a/src/boost/libs/hana/test/_include/laws/comparable.hpp b/src/boost/libs/hana/test/_include/laws/comparable.hpp new file mode 100644 index 000000000..24ce317b8 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/comparable.hpp @@ -0,0 +1,167 @@ +// 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_COMPARABLE_HPP +#define BOOST_HANA_TEST_LAWS_COMPARABLE_HPP + +#include <boost/hana/and.hpp> +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/comparing.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/constant.hpp> +#include <boost/hana/concept/product.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/first.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/not_equal.hpp> +#include <boost/hana/second.hpp> +#include <boost/hana/value.hpp> + + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename T, typename = hana::when<true>> + struct TestComparable : TestComparable<T, laws> { + using TestComparable<T, laws>::TestComparable; + }; + + template <typename T> + struct TestComparable<T, laws> { + template <typename Xs> + TestComparable(Xs xs) { + hana::for_each(xs, [](auto x) { + static_assert(hana::Comparable<decltype(x)>{}, ""); + }); + + foreach2(xs, [](auto a, auto b) { + + // reflexivity + BOOST_HANA_CHECK( + hana::equal(a, a) + ); + + // symmetry + BOOST_HANA_CHECK( + hana::equal(a, b) ^implies^ hana::equal(b, a) + ); + + // `not_equal` is the negation of `equal` + BOOST_HANA_CHECK( + hana::not_equal(a, b) ^iff^ hana::not_(hana::equal(a, b)) + ); + + // equal.to and not_equal.to + BOOST_HANA_CHECK( + hana::equal.to(a)(b) ^iff^ hana::equal(a, b) + ); + + BOOST_HANA_CHECK( + hana::not_equal.to(a)(b) ^iff^ hana::not_equal(a, b) + ); + + // comparing + _injection<0> f{}; + BOOST_HANA_CHECK( + hana::comparing(f)(a, b) ^iff^ hana::equal(f(a), f(b)) + ); + }); + + // transitivity + foreach3(xs, [](auto a, auto b, auto c) { + BOOST_HANA_CHECK( + hana::and_(hana::equal(a, b), hana::equal(b, c)) + ^implies^ hana::equal(a, c) + ); + }); + } + }; + + template <typename C> + struct TestComparable<C, when<Constant<C>::value>> + : TestComparable<C, laws> + { + template <typename Xs> + TestComparable(Xs xs) : TestComparable<C, laws>{xs} { + foreach2(xs, [](auto a, auto b) { + BOOST_HANA_CHECK( + hana::value(hana::equal(a, b)) ^iff^ + hana::equal(hana::value(a), hana::value(b)) + ); + }); + } + }; + + template <typename P> + struct TestComparable<P, when<Product<P>::value>> + : TestComparable<P, laws> + { + template <typename Products> + TestComparable(Products products) : TestComparable<P, laws>{products} { + foreach2(products, [](auto x, auto y) { + BOOST_HANA_CHECK( + hana::equal(x, y) ^iff^ + hana::and_( + hana::equal(hana::first(x), hana::first(y)), + hana::equal(hana::second(x), hana::second(y)) + ) + ); + }); + } + }; + + template <typename S> + struct TestComparable<S, when<Sequence<S>::value>> + : TestComparable<S, laws> + { + template <int i> + using x = _constant<i>; + + template <typename Xs> + TestComparable(Xs xs) : TestComparable<S, laws>{xs} { + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // equal + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(hana::equal( + list(), + list() + )); + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( + list(x<0>{}), + list() + ))); + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( + list(), + list(x<0>{}) + ))); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + list(x<0>{}), + list(x<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( + list(x<0>{}, x<1>{}), + list(x<0>{}) + ))); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + list(x<0>{}, x<1>{}), + list(x<0>{}, x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::equal( + list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), + list(x<0>{}, x<1>{}, x<2>{}, x<4>{}) + ))); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_COMPARABLE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/constant.hpp b/src/boost/libs/hana/test/_include/laws/constant.hpp new file mode 100644 index 000000000..1acd335e4 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/constant.hpp @@ -0,0 +1,106 @@ +// 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_CONSTANT_HPP +#define BOOST_HANA_TEST_LAWS_CONSTANT_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/concept/logical.hpp> + +#include <laws/base.hpp> +#include <laws/comparable.hpp> +#include <laws/euclidean_ring.hpp> +#include <laws/group.hpp> +#include <laws/logical.hpp> +#include <laws/monoid.hpp> +#include <laws/orderable.hpp> +#include <laws/ring.hpp> + +#include <type_traits> + + +namespace boost { namespace hana { namespace test { + template <typename C, typename = when<true>> + struct TestConstant { + using T = typename C::value_type; + + template <typename X> + struct wrap_arbitrary_constant { + static constexpr bool value = boost::hana::value<X>(); + using hana_tag = detail::CanonicalConstant<T>; + }; + + template <typename Xs, typename Convertibles> + TestConstant(Xs xs, Convertibles types) { + hana::for_each(xs, [](auto x) { + static_assert(Constant<decltype(x)>{}, ""); + }); + + hana::for_each(xs, hana::capture(types)([](auto types, auto c) { + + // constexpr-ness of hana::value(c) + constexpr auto must_be_constexpr1 = hana::value(c); + constexpr auto must_be_constexpr2 = hana::value<decltype(c)>(); + (void)must_be_constexpr1; + (void)must_be_constexpr2; + + // consistency of C::value_type + static_assert(std::is_same< + T, + tag_of_t<decltype(hana::value(c))> + >{}, ""); + + // equivalence of value_of(c) and value<decltype(c)> + BOOST_HANA_CHECK(hana::equal( + hana::value_of(c), + hana::value<decltype(c)>() + )); + + // equivalence of value<decltype(c)>() and value(c) + BOOST_HANA_CHECK(hana::equal( + hana::value<decltype(c)>(), + hana::value(c) + )); + + // conversion from an arbitrary Constant + (void)to<C>(wrap_arbitrary_constant<decltype(c)>{}); + static_assert(is_embedded<detail::CanonicalConstant<T>, C>{}, ""); + + hana::for_each(types, hana::capture(c)([](auto c, auto u) { + using U = typename decltype(u)::type; + + // conversion to something to which the underlying data + // type can be converted. + BOOST_HANA_CHECK(equal( + to<U>(c), + make<U>(hana::value(c)) + )); + static_assert(is_embedded<C, U>::value ^iff^ is_embedded<T, U>::value, ""); + + // common data type + static_assert(std::is_same< + common_t<C, detail::CanonicalConstant<U>>, + detail::CanonicalConstant<common_t<T, U>> + >{}, ""); + + static_assert(std::is_same< + common_t<detail::CanonicalConstant<U>, C>, + detail::CanonicalConstant<common_t<T, U>> + >{}, ""); + + static_assert(std::is_same< + common_t<C, U>, + common_t<typename C::value_type, U> + >{}, ""); + })); + })); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_CONSTANT_HPP diff --git a/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp b/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp new file mode 100644 index 000000000..96d1fce58 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/euclidean_ring.hpp @@ -0,0 +1,99 @@ +// 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_EUCLIDEAN_RING_HPP +#define BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/constant.hpp> +#include <boost/hana/concept/euclidean_ring.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/div.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/mod.hpp> +#include <boost/hana/mult.hpp> +#include <boost/hana/not_equal.hpp> +#include <boost/hana/plus.hpp> +#include <boost/hana/value.hpp> +#include <boost/hana/zero.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename D, typename = when<true>> + struct TestEuclideanRing : TestEuclideanRing<D, laws> { + using TestEuclideanRing<D, laws>::TestEuclideanRing; + }; + + template <typename D> + struct TestEuclideanRing<D, laws> { + template <typename Xs> + TestEuclideanRing(Xs xs) { + hana::for_each(xs, [](auto x) { + static_assert(EuclideanRing<decltype(x)>{}, ""); + }); + +#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735 + zero<D>(); // force adding zero<D>'s member function to pending temploid list +#endif + + foreach2(xs, [](auto a, auto b) { + + // commutativity + BOOST_HANA_CHECK(hana::equal( + hana::mult(a, b), + hana::mult(b, a) + )); + + only_when_(hana::not_equal(b, zero<D>()), + hana::make_lazy([](auto a, auto b) { + BOOST_HANA_CHECK(hana::equal( + hana::plus( + hana::mult(hana::div(a, b), b), + hana::mod(a, b) + ), + a + )); + + BOOST_HANA_CHECK(hana::equal( + hana::mod(zero<D>(), b), + zero<D>() + )); + })(a, b)); + + }); + } + }; + + template <typename C> + struct TestEuclideanRing<C, when<Constant<C>::value>> + : TestEuclideanRing<C, laws> + { + template <typename Xs> + TestEuclideanRing(Xs xs) : TestEuclideanRing<C, laws>{xs} { + foreach2(xs, [](auto x, auto y) { + only_when_(hana::not_equal(zero<C>(), y), + hana::make_lazy([](auto x, auto y) { + BOOST_HANA_CHECK(hana::equal( + hana::div(hana::value(x), hana::value(y)), + hana::value(hana::div(x, y)) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::mod(hana::value(x), hana::value(y)), + hana::value(hana::mod(x, y)) + )); + + })(x, y)); + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_EUCLIDEAN_RING_HPP diff --git a/src/boost/libs/hana/test/_include/laws/foldable.hpp b/src/boost/libs/hana/test/_include/laws/foldable.hpp new file mode 100644 index 000000000..57411f416 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/foldable.hpp @@ -0,0 +1,1104 @@ +// 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_FOLDABLE_HPP +#define BOOST_HANA_TEST_LAWS_FOLDABLE_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/chain.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/foldable.hpp> +#include <boost/hana/concept/product.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/config.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/count.hpp> +#include <boost/hana/count_if.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/first.hpp> +#include <boost/hana/fold.hpp> +#include <boost/hana/fold_left.hpp> +#include <boost/hana/fold_right.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/functional/curry.hpp> +#include <boost/hana/functional/demux.hpp> +#include <boost/hana/functional/flip.hpp> +#include <boost/hana/integral_constant.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/length.hpp> +#include <boost/hana/lift.hpp> +#include <boost/hana/maximum.hpp> +#include <boost/hana/minimum.hpp> +#include <boost/hana/monadic_fold_left.hpp> +#include <boost/hana/monadic_fold_right.hpp> +#include <boost/hana/not_equal.hpp> +#include <boost/hana/product.hpp> +#include <boost/hana/reverse_fold.hpp> +#include <boost/hana/second.hpp> +#include <boost/hana/size.hpp> +#include <boost/hana/sum.hpp> +#include <boost/hana/unpack.hpp> +#include <boost/hana/value.hpp> + +#include <laws/base.hpp> +#include <support/identity.hpp> + +#include <vector> + + +namespace boost { namespace hana { namespace test { + template <typename F, typename = when<true>> + struct TestFoldable : TestFoldable<F, laws> { + using TestFoldable<F, laws>::TestFoldable; + }; + + template <typename F> + struct TestFoldable<F, laws> { + template <typename Foldables> + TestFoldable(Foldables foldables) { + hana::for_each(foldables, [](auto xs) { + static_assert(Foldable<decltype(xs)>{}, ""); + + _injection<0> f{}; + ct_eq<999> s{}; + + // equivalence of size(xs) and length(xs) + BOOST_HANA_CHECK(hana::equal( + hana::length(xs), + hana::size(xs) + )); + + // equivalence of fold with fold_left and + // of reverse_fold with fold_right + BOOST_HANA_CHECK(hana::equal( + hana::fold(xs, s, f), + hana::fold_left(xs, s, f) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::reverse_fold(xs, s, f), + hana::fold_right(xs, s, hana::flip(f)) + )); + + only_when_(hana::not_equal(hana::length(xs), hana::size_c<0>), + hana::make_lazy([](auto f, auto xs) { + BOOST_HANA_CHECK(hana::equal( + hana::fold(xs, f), + hana::fold_left(xs, f) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::reverse_fold(xs, f), + hana::fold_right(xs, hana::flip(f)) + )); + })(f, xs)); + + // equivalence of count(xs, val) and count_if(xs, equal.to(val)) + struct not_there { }; + BOOST_HANA_CHECK(hana::equal( + hana::count(xs, not_there{}), + hana::count_if(xs, equal.to(not_there{})) + )); + + hana::for_each(xs, hana::capture(xs)([](auto xs, auto value) { + BOOST_HANA_CHECK(hana::equal( + hana::count(xs, value), + hana::count_if(xs, equal.to(value)) + )); + })); + }); + } + }; + + template <typename P> + struct TestFoldable<P, when<Product<P>::value>> + : TestFoldable<P, laws> + { + template <typename Products> + TestFoldable(Products products) : TestFoldable<P, laws>{products} { + hana::for_each(products, [](auto p) { + _injection<0> f{}; + + BOOST_HANA_CHECK(hana::equal( + hana::unpack(p, f), + f(hana::first(p), hana::second(p)) + )); + }); + } + }; + + template <typename S> + struct TestFoldable<S, when<Sequence<S>::value>> + : TestFoldable<S, laws> + { + template <int i> + using x = _constant<i>; + + template <int i> + using ord = _constant<i>; + + struct undefined { }; + + template <typename Xs> + TestFoldable(Xs xs) : TestFoldable<S, laws>{xs} { + _injection<0> f{}; + auto z = x<999>{}; + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // fold_left (with initial state) + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(), z, undefined{}), + z + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(x<1>{}), z, f), + f(z, x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(x<1>{}, x<2>{}), z, f), + f(f(z, x<1>{}), x<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(x<1>{}, x<2>{}, x<3>{}), z, f), + f(f(f(z, x<1>{}), x<2>{}), x<3>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), z, f), + f(f(f(f(z, x<1>{}), x<2>{}), x<3>{}), x<4>{}) + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_left(list(1), z, f), + f(z, 1) + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_left(list(1, '2'), z, f), + f(f(z, 1), '2') + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_left(list(1, '2', 3.3), z, f), + f(f(f(z, 1), '2'), 3.3) + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_left(list(1, '2', 3.3, 4.4f), z, f), + f(f(f(f(z, 1), '2'), 3.3), 4.4f) + )); + + ////////////////////////////////////////////////////////////////// + // fold_left (without initial state) + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(z), undefined{}), + z + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(z, x<2>{}), f), + f(z, x<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(z, x<2>{}, x<3>{}), f), + f(f(z, x<2>{}), x<3>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_left(list(z, x<2>{}, x<3>{}, x<4>{}), f), + f(f(f(z, x<2>{}), x<3>{}), x<4>{}) + )); + + ////////////////////////////////////////////////////////////////// + // fold_right (with initial state) + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(), z, undefined{}), + z + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(x<0>{}), z, f), + f(x<0>{}, z) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(x<0>{}, x<1>{}), z, f), + f(x<0>{}, f(x<1>{}, z)) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(x<0>{}, x<1>{}, x<2>{}), z, f), + f(x<0>{}, f(x<1>{}, f(x<2>{}, z))) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), z, f), + f(x<0>{}, f(x<1>{}, f(x<2>{}, f(x<3>{}, z)))) + )); + + + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_right(list(1), z, f), + f(1, z) + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_right(list(1, '2'), z, f), + f(1, f('2', z)) + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_right(list(1, '2', 3.3), z, f), + f(1, f('2', f(3.3, z))) + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + fold_right(list(1, '2', 3.3, 4.4f), z, f), + f(1, f('2', f(3.3, f(4.4f, z)))) + )); + + ////////////////////////////////////////////////////////////////// + // fold_right (without initial state) + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(z), undefined{}), + z + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(x<1>{}, z), f), + f(x<1>{}, z) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(x<1>{}, x<2>{}, z), f), + f(x<1>{}, f(x<2>{}, z)) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + fold_right(list(x<1>{}, x<2>{}, x<3>{}, z), f), + f(x<1>{}, f(x<2>{}, f(x<3>{}, z))) + )); + + ////////////////////////////////////////////////////////////////// + // monadic_fold_left (with initial state) + ////////////////////////////////////////////////////////////////// + { + using M = ::Identity; + auto f = hana::demux(::identity)(test::_injection<0>{}); + auto s = x<999>{}; + auto fp = hana::curry<2>(hana::flip(f)); + constexpr auto mfold = monadic_fold_left<M>; + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(), s, undefined{}), + lift<M>(s) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}), s, f), + f(s, x<1>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}), s, f), + chain(f(s, x<1>{}), fp(x<2>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}), s, f), + chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), s, f), + chain(chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{})), fp(x<4>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), s, f), + chain(chain(chain(chain(f(s, x<1>{}), fp(x<2>{})), fp(x<3>{})), fp(x<4>{})), fp(x<5>{})) + )); + } + + ////////////////////////////////////////////////////////////////// + // monadic_fold_left (without initial state) + ////////////////////////////////////////////////////////////////// + { + using M = ::Identity; + auto f = hana::demux(::identity)(test::_injection<0>{}); + auto fp = hana::curry<2>(hana::flip(f)); + constexpr auto mfold = monadic_fold_left<M>; + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}), undefined{}), + lift<M>(x<1>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}), f), + f(x<1>{}, x<2>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}), f), + chain(f(x<1>{}, x<2>{}), fp(x<3>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), f), + chain(chain(f(x<1>{}, x<2>{}), fp(x<3>{})), fp(x<4>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), f), + chain(chain(chain(f(x<1>{}, x<2>{}), fp(x<3>{})), fp(x<4>{})), fp(x<5>{})) + )); + } + + ////////////////////////////////////////////////////////////////// + // monadic_fold_right (with initial state) + ////////////////////////////////////////////////////////////////// + { + using M = ::Identity; + auto f = hana::demux(::identity)(test::_injection<0>{}); + auto s = x<999>{}; + auto fp = hana::curry<2>(f); + // flipping `chain` makes the right associativity easier to see + auto chain = hana::flip(hana::chain); + constexpr auto mfold = monadic_fold_right<M>; + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(), s, undefined{}), + lift<M>(s) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}), s, f), + f(x<1>{}, s) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}), s, f), + chain(fp(x<1>{}), f(x<2>{}, s)) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}), s, f), + chain(fp(x<1>{}), chain(fp(x<2>{}), f(x<3>{}, s))) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), s, f), + chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), f(x<4>{}, s)))) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), s, f), + chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), chain(fp(x<4>{}), f(x<5>{}, s))))) + )); + } + + ////////////////////////////////////////////////////////////////// + // monadic_fold_right (without initial state) + ////////////////////////////////////////////////////////////////// + { + using M = ::Identity; + auto f = hana::demux(::identity)(test::_injection<0>{}); + auto fp = hana::curry<2>(f); + // flipping `chain` makes the right associativity easier to see + auto chain = hana::flip(hana::chain); + constexpr auto mfold = monadic_fold_right<M>; + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}), undefined{}), + lift<M>(x<1>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}), f), + f(x<1>{}, x<2>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}), f), + chain(fp(x<1>{}), f(x<2>{}, x<3>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}), f), + chain(fp(x<1>{}), chain(fp(x<2>{}), f(x<3>{}, x<4>{}))) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + mfold(list(x<1>{}, x<2>{}, x<3>{}, x<4>{}, x<5>{}), f), + chain(fp(x<1>{}), chain(fp(x<2>{}), chain(fp(x<3>{}), f(x<4>{}, x<5>{})))) + )); + } + + ////////////////////////////////////////////////////////////////// + // length + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + length(list()), size_c<0> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + length(list(undefined{})), size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + length(list(undefined{}, undefined{})), size_c<2> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + length(list(undefined{}, undefined{}, undefined{})), size_c<3> + )); + + int i = 0; // non-constexpr + BOOST_HANA_CONSTANT_CHECK(equal( + length(list(i, i)), + size_c<2> + )); + + ////////////////////////////////////////////////////////////////// + // maximum (without a custom predicate) + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<0>{})), + ord<0>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<0>{}, ord<1>{})), + ord<1>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<1>{}, ord<0>{})), + ord<1>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<0>{}, ord<1>{}, ord<2>{})), + ord<2>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<1>{}, ord<0>{}, ord<2>{})), + ord<2>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<1>{}, ord<2>{}, ord<0>{})), + ord<2>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<2>{}, ord<1>{}, ord<0>{})), + ord<2>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<2>{}, ord<0>{}, ord<1>{})), + ord<2>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<0>{}, ord<1>{}, ord<2>{}, ord<3>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<1>{}, ord<0>{}, ord<2>{}, ord<3>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<1>{}, ord<2>{}, ord<0>{}, ord<3>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<1>{}, ord<2>{}, ord<3>{}, ord<0>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<2>{}, ord<1>{}, ord<3>{}, ord<0>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<2>{}, ord<3>{}, ord<1>{}, ord<0>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<2>{}, ord<3>{}, ord<0>{}, ord<1>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<3>{}, ord<2>{}, ord<0>{}, ord<1>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<3>{}, ord<0>{}, ord<2>{}, ord<1>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<3>{}, ord<0>{}, ord<1>{}, ord<2>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<0>{}, ord<2>{}, ord<3>{}, ord<1>{})), + ord<3>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + maximum(list(ord<0>{}, ord<3>{}, ord<1>{}, ord<2>{})), + ord<3>{} + )); + + + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0})), + int{0} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0}, long{1})), + long{1} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{1}, long{0})), + int{1} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0}, 1ll, long{2})), + long{2} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{1}, 0ll, long{2})), + long{2} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{1}, 2ll, long{0})), + 2ll + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{2}, 1ll, long{0})), + int{2} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{2}, 0ll, long{1})), + int{2} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0}, 1ll, long{2}, short{3})), + short{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{1}, 0ll, long{2}, short{3})), + short{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{1}, 2ll, long{0}, short{3})), + short{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{1}, 2ll, long{3}, short{0})), + long{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{2}, 1ll, long{3}, short{0})), + long{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{2}, 3ll, long{1}, short{0})), + 3ll + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{2}, 3ll, long{0}, short{1})), + 3ll + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{3}, 2ll, long{0}, short{1})), + int{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{3}, 0ll, long{2}, short{1})), + int{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{3}, 0ll, long{1}, short{2})), + int{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0}, 2ll, long{3}, short{1})), + long{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0}, 3ll, long{1}, short{2})), + 3ll + )); + + + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0}, 1ll, long_c<2>)), + long{2} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + maximum(list(int{0}, long_c<1>, 2ll)), + 2ll + )); + } + + ////////////////////////////////////////////////////////////////// + // minimum (without a custom predicate) + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<6>{})), + ord<6>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<6>{}, ord<7>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<7>{}, ord<6>{})), + ord<6>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<6>{}, ord<7>{}, ord<8>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<7>{}, ord<6>{}, ord<8>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<7>{}, ord<8>{}, ord<6>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<8>{}, ord<7>{}, ord<6>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<8>{}, ord<6>{}, ord<7>{})), + ord<6>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<6>{}, ord<7>{}, ord<8>{}, ord<9>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<7>{}, ord<6>{}, ord<8>{}, ord<9>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<7>{}, ord<8>{}, ord<6>{}, ord<9>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<7>{}, ord<8>{}, ord<9>{}, ord<6>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<8>{}, ord<7>{}, ord<9>{}, ord<6>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<8>{}, ord<9>{}, ord<7>{}, ord<6>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<8>{}, ord<9>{}, ord<6>{}, ord<7>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<9>{}, ord<8>{}, ord<6>{}, ord<7>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<9>{}, ord<6>{}, ord<8>{}, ord<7>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<9>{}, ord<6>{}, ord<7>{}, ord<8>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<6>{}, ord<8>{}, ord<9>{}, ord<7>{})), + ord<6>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + minimum(list(ord<6>{}, ord<9>{}, ord<7>{}, ord<8>{})), + ord<6>{} + )); + + + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{4})), + int{4} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{4}, short{5})), + int{4} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{5}, short{4})), + short{4} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{4}, short{5}, long{6})), + int{4} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{7}, short{6}, long{8})), + short{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{7}, short{8}, long{6})), + long{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{8}, short{7}, long{6})), + long{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{8}, short{6}, long{7})), + short{6} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{6}, short{7}, long{8}, 9ll)), + int{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{7}, short{6}, long{8}, 9ll)), + short{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{7}, short{8}, long{6}, 9ll)), + long{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{7}, short{8}, long{9}, 6ll)), + 6ll + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{8}, short{7}, long{9}, 6ll)), + 6ll + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{8}, short{9}, long{7}, 6ll)), + 6ll + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{8}, short{9}, long{6}, 7ll)), + long{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{9}, short{8}, long{6}, 7ll)), + long{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{9}, short{6}, long{8}, 7ll)), + short{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{9}, short{6}, long{7}, 8ll)), + short{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{6}, short{8}, long{9}, 7ll)), + int{6} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{6}, short{9}, long{7}, 8ll)), + int{6} + )); + + + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(int{3}, short{4}, long_c<5>)), + int{3} + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + minimum(list(ord<33>{}, short{45}, long{46})), + ord<33>{} + )); + } + + + ////////////////////////////////////////////////////////////////// + // count_if + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(), id), size_c<0> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<1>), id), size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<0>), id), size_c<0> + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<1>, char_c<1>), id), size_c<2> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<1>, char_c<0>), id), size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<0>, char_c<1>), id), size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<0>, char_c<0>), id), size_c<0> + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<1>, char_c<1>, long_c<1>), id), size_c<3> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<1>, char_c<1>, long_c<0>), id), size_c<2> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<1>, char_c<0>, long_c<1>), id), size_c<2> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<1>, char_c<0>, long_c<0>), id), size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<0>, char_c<1>, long_c<1>), id), size_c<2> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<0>, char_c<1>, long_c<0>), id), size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<0>, char_c<0>, long_c<1>), id), size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + count_if(list(int_c<0>, char_c<0>, long_c<0>), id), size_c<0> + )); + + + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{1}), id), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{0}), id), 0u + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{1}, char{1}), id), 2u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{1}, char{0}), id), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{0}, char{1}), id), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{0}, char{0}), id), 0u + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{1}, char{1}, double{1}), id), 3u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{1}, char{1}, double{0}), id), 2u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{1}, char{0}, double{1}), id), 2u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{1}, char{0}, double{0}), id), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{0}, char{1}, double{1}), id), 2u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{0}, char{1}, double{0}), id), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{0}, char{0}, double{1}), id), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(int{0}, char{0}, double{0}), id), 0u + )); + + + BOOST_HANA_CONSTEXPR_LAMBDA auto is_even = [](auto x) { + return x % 2 == 0; + }; + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(), is_even), 0u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(1), is_even), 0u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(2), is_even), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(1, 2), is_even), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(1, 2, 3), is_even), 1u + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + count_if(list(1, 2, 3, 4), is_even), 2u + )); + + ////////////////////////////////////////////////////////////////// + // count + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::count(list(), undefined{}), + size_c<0> + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::count(list(ct_eq<0>{}), undefined{}), + size_c<0> + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::count(list(ct_eq<0>{}), ct_eq<0>{}), + size_c<1> + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::count(list(ct_eq<0>{}, ct_eq<1>{}), undefined{}), + size_c<0> + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::count(list(ct_eq<0>{}, ct_eq<1>{}), ct_eq<0>{}), + size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::count(list(ct_eq<0>{}, ct_eq<1>{}), ct_eq<1>{}), + size_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::count(list(ct_eq<0>{}, ct_eq<0>{}), ct_eq<0>{}), + size_c<2> + )); + + ////////////////////////////////////////////////////////////////// + // product + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + product<integral_constant_tag<int>>(list()), + int_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + product<integral_constant_tag<int>>(list(int_c<2>)), + int_c<2> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>)), + int_c<2 * 3> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>, int_c<4>)), + int_c<2 * 3 * 4> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + product<integral_constant_tag<int>>(list(int_c<2>, int_c<3>, int_c<4>, int_c<5>)), + int_c<2 * 3 * 4 * 5> + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + product<integral_constant_tag<unsigned long>>(list()), + ulong_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + product<integral_constant_tag<unsigned long>>(list(ulong_c<2>, ulong_c<3>, ulong_c<4>)), + ulong_c<2 * 3 * 4> + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + product<int>(list(2)), + 2 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + product<int>(list(2, 3)), + 2 * 3 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + product<int>(list(2, 3, 4)), + 2 * 3 * 4 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + product<int>(list(2, 3, 4, 5)), + 2 * 3 * 4 * 5 + )); + + + ////////////////////////////////////////////////////////////////// + // sum + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + sum<integral_constant_tag<int>>(list()), + int_c<0> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + sum<integral_constant_tag<int>>(list(int_c<1>)), + int_c<1> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>)), + int_c<1 + 2> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>, int_c<3>)), + int_c<1 + 2 + 3> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + sum<integral_constant_tag<int>>(list(int_c<1>, int_c<2>, int_c<3>, int_c<4>)), + int_c<1 + 2 + 3 + 4> + )); + + + BOOST_HANA_CONSTANT_CHECK(equal( + sum<integral_constant_tag<unsigned long>>(list()), + ulong_c<0> + )); + BOOST_HANA_CONSTANT_CHECK(equal( + sum<integral_constant_tag<unsigned long>>(list(ulong_c<1>, ulong_c<2>, ulong_c<3>)), + ulong_c<1 + 2 + 3> + )); + + + BOOST_HANA_CONSTEXPR_CHECK(equal( + sum<int>(list(1)), 1 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + sum<int>(list(1, 2)), 1 + 2 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + sum<int>(list(1, 2, 3)), 1 + 2 + 3 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + sum<int>(list(1, 2, 3, 4)), 1 + 2 + 3 + 4 + )); + + + ////////////////////////////////////////////////////////////////// + // unpack + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + unpack(list(), f), + f() + )); + BOOST_HANA_CONSTANT_CHECK(equal( + unpack(list(x<0>{}), f), + f(x<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + unpack(list(x<0>{}, x<1>{}), f), + f(x<0>{}, x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + unpack(list(x<0>{}, x<1>{}, x<2>{}), f), + f(x<0>{}, x<1>{}, x<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + unpack(list(x<0>{}, x<1>{}, x<2>{}, x<3>{}), f), + f(x<0>{}, x<1>{}, x<2>{}, x<3>{}) + )); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_FOLDABLE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/functor.hpp b/src/boost/libs/hana/test/_include/laws/functor.hpp new file mode 100644 index 000000000..d1ddbb4de --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/functor.hpp @@ -0,0 +1,250 @@ +// 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_FUNCTOR_HPP +#define BOOST_HANA_TEST_LAWS_FUNCTOR_HPP + +#include <boost/hana/adjust.hpp> +#include <boost/hana/adjust_if.hpp> +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/functor.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/eval_if.hpp> +#include <boost/hana/fill.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/functional/always.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/functional/compose.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/replace.hpp> +#include <boost/hana/replace_if.hpp> +#include <boost/hana/transform.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename F, typename = when<true>> + struct TestFunctor : TestFunctor<F, laws> { + using TestFunctor<F, laws>::TestFunctor; + }; + + template <typename F> + struct TestFunctor<F, laws> { + template <typename Xs, typename Elements> + TestFunctor(Xs xs, Elements elements) { + hana::for_each(xs, hana::capture(elements)([](auto elements, auto x) { + static_assert(Functor<decltype(x)>{}, ""); + + test::_injection<0> f{}; + test::_injection<1> g{}; + + // identity + BOOST_HANA_CHECK(hana::equal( + hana::transform(x, id), + x + )); + + // composition + BOOST_HANA_CHECK(hana::equal( + hana::transform(x, hana::compose(f, g)), + hana::transform(hana::transform(x, g), f) + )); + + // method definitions in terms of transform/adjust_if + hana::for_each(elements, hana::capture(x, f, elements)( + [](auto x, auto f, auto elements, auto value) { + BOOST_HANA_CHECK(hana::equal( + hana::adjust(x, value, f), + hana::adjust_if(x, hana::equal.to(value), f) + )); + + hana::for_each(elements, hana::capture(x, value)( + [](auto x, auto oldval, auto newval) { + BOOST_HANA_CHECK(hana::equal( + hana::replace(x, oldval, newval), + hana::replace_if(x, hana::equal.to(oldval), newval) + )); + })); + })); + + auto pred = hana::always(true_c); + BOOST_HANA_CHECK(hana::equal( + hana::adjust_if(x, pred, f), + hana::transform(x, [=](auto z) { + return hana::eval_if(pred(z), + hana::make_lazy(f)(z), + hana::make_lazy(z) + ); + }) + )); + + test::_constant<0> v{}; + BOOST_HANA_CHECK(hana::equal( + hana::replace_if(x, pred, v), + hana::adjust_if(x, pred, hana::always(v)) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::fill(x, v), + hana::replace_if(x, hana::always(true_c), v) + )); + + })); + } + }; + + template <typename S> + struct TestFunctor<S, when<Sequence<S>::value>> + : TestFunctor<S, laws> + { + struct undefined { }; + + template <typename Xs, typename Elements> + TestFunctor(Xs xs, Elements elements) + : TestFunctor<S, laws>{xs, elements} + { + using test::ct_eq; + using test::cx_eq; + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // replace_if + ////////////////////////////////////////////////////////////////// + { + auto a = ct_eq<888>{}; + auto b = ct_eq<999>{}; + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(), undefined{}, undefined{}), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(ct_eq<0>{}), equal.to(a), undefined{}), + list(ct_eq<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(a), equal.to(a), b), + list(b) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}), equal.to(a), undefined{}), + list(ct_eq<0>{}, ct_eq<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(a, ct_eq<1>{}), equal.to(a), b), + list(b, ct_eq<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(ct_eq<0>{}, a), equal.to(a), b), + list(ct_eq<0>{}, b) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(a, a), equal.to(a), b), + list(b, b) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), undefined{}), + list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(a, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), b), + list(b, ct_eq<1>{}, ct_eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(ct_eq<0>{}, a, ct_eq<2>{}), equal.to(a), b), + list(ct_eq<0>{}, b, ct_eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, a), equal.to(a), b), + list(ct_eq<0>{}, ct_eq<1>{}, b) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(a, ct_eq<1>{}, a), equal.to(a), b), + list(b, ct_eq<1>{}, b) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace_if(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), equal.to(a), b), + list(b, ct_eq<1>{}, b, ct_eq<3>{}, b) + )); + } + + ////////////////////////////////////////////////////////////////// + // replace + ////////////////////////////////////////////////////////////////// + { + auto a = ct_eq<888>{}; + auto b = ct_eq<999>{}; + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(), undefined{}, undefined{}), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(ct_eq<0>{}), a, undefined{}), + list(ct_eq<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(a), a, b), + list(b) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(ct_eq<0>{}, ct_eq<1>{}), a, undefined{}), + list(ct_eq<0>{}, ct_eq<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(a, ct_eq<1>{}), a, b), + list(b, ct_eq<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(ct_eq<0>{}, a), a, b), + list(ct_eq<0>{}, b) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(a, a), a, b), + list(b, b) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), a, undefined{}), + list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(a, ct_eq<1>{}, ct_eq<2>{}), a, b), + list(b, ct_eq<1>{}, ct_eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(ct_eq<0>{}, a, ct_eq<2>{}), a, b), + list(ct_eq<0>{}, b, ct_eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, a), a, b), + list(ct_eq<0>{}, ct_eq<1>{}, b) + )); + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(a, ct_eq<1>{}, a), a, b), + list(b, ct_eq<1>{}, b) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::replace(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), a, b), + list(b, ct_eq<1>{}, b, ct_eq<3>{}, b) + )); + } + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_FUNCTOR_HPP diff --git a/src/boost/libs/hana/test/_include/laws/group.hpp b/src/boost/libs/hana/test/_include/laws/group.hpp new file mode 100644 index 000000000..b9eeab776 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/group.hpp @@ -0,0 +1,93 @@ +// 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_GROUP_HPP +#define BOOST_HANA_TEST_LAWS_GROUP_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/concept/group.hpp> +#include <boost/hana/lazy.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename G, typename = when<true>> + struct TestGroup : TestGroup<G, laws> { + using TestGroup<G, laws>::TestGroup; + }; + + template <typename G> + struct TestGroup<G, laws> { + template <typename Xs> + TestGroup(Xs xs) { + hana::for_each(xs, [](auto x) { + static_assert(Group<decltype(x)>{}, ""); + }); + +#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735 + zero<G>(); // force adding zero<G>'s member function to pending temploid list +#endif + + foreach2(xs, [](auto x, auto y) { + + // left inverse + BOOST_HANA_CHECK(hana::equal( + hana::plus(x, hana::negate(x)), + zero<G>() + )); + + // right inverse + BOOST_HANA_CHECK(hana::equal( + hana::plus(hana::negate(x), x), + zero<G>() + )); + + // default definition of minus + BOOST_HANA_CHECK(hana::equal( + hana::minus(x, y), + hana::plus(x, hana::negate(y)) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::minus(y, x), + hana::plus(y, hana::negate(x)) + )); + + // default definition of negate + BOOST_HANA_CHECK(hana::equal( + hana::negate(hana::negate(x)), + x + )); + }); + } + }; + + template <typename C> + struct TestGroup<C, when<Constant<C>::value>> + : TestGroup<C, laws> + { + template <typename Xs> + TestGroup(Xs xs) : TestGroup<C, laws>{xs} { + foreach2(xs, [](auto x, auto y) { + + BOOST_HANA_CHECK(hana::equal( + hana::negate(hana::value(x)), + hana::value(hana::negate(x)) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::minus(hana::value(x), hana::value(y)), + hana::value(hana::minus(x, y)) + )); + + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_GROUP_HPP diff --git a/src/boost/libs/hana/test/_include/laws/hashable.hpp b/src/boost/libs/hana/test/_include/laws/hashable.hpp new file mode 100644 index 000000000..0fbd8f333 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/hashable.hpp @@ -0,0 +1,60 @@ +// 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_HASHABLE_HPP +#define BOOST_HANA_TEST_LAWS_HASHABLE_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/hashable.hpp> +#include <boost/hana/core/default.hpp> +#include <boost/hana/core/tag_of.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/hash.hpp> +#include <boost/hana/if.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename G, typename = when<true>> + struct TestHashable : TestHashable<G, laws> { + using TestHashable<G, laws>::TestHashable; + }; + + template <typename H> + struct TestHashable<H, laws> { + template <typename Xs> + TestHashable(Xs xs) { + hana::for_each(xs, [](auto x) { + static_assert(Hashable<decltype(x)>{}, ""); + }); + + hana::for_each(xs, [&](auto const& x) { + hana::for_each(xs, [&](auto const& y) { + using X = hana::tag_of_t<decltype(x)>; + using Y = hana::tag_of_t<decltype(y)>; + constexpr bool comparable = !hana::is_default< + hana::equal_impl<X, Y> + >::value; + + hana::if_(hana::bool_c<comparable>, + [](auto const& x, auto const& y) { + BOOST_HANA_CHECK( + hana::equal(x, y) + ^implies^ + hana::equal(hana::hash(x), hana::hash(y)) + ); + }, + [](auto...) { } + )(x, y); + }); + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_HASHABLE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/iterable.hpp b/src/boost/libs/hana/test/_include/laws/iterable.hpp new file mode 100644 index 000000000..d6d84c5ec --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/iterable.hpp @@ -0,0 +1,195 @@ +// 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_ITERABLE_HPP +#define BOOST_HANA_TEST_LAWS_ITERABLE_HPP + +#include <boost/hana/any_of.hpp> +#include <boost/hana/assert.hpp> +#include <boost/hana/at.hpp> +#include <boost/hana/back.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/foldable.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/to.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/drop_front.hpp> +#include <boost/hana/drop_front_exactly.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/eval_if.hpp> +#include <boost/hana/find_if.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/front.hpp> +#include <boost/hana/functional/always.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/integral_constant.hpp> +#include <boost/hana/is_empty.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/length.hpp> +#include <boost/hana/minus.hpp> +#include <boost/hana/not.hpp> +#include <boost/hana/optional.hpp> +#include <boost/hana/range.hpp> +#include <boost/hana/tuple.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename It, typename = hana::when<true>> + struct TestIterable : TestIterable<It, laws> { + using TestIterable<It, laws>::TestIterable; + }; + + template <typename It> + struct TestIterable<It, laws> { + template <typename Xs> + TestIterable(Xs xs) { + hana::for_each(xs, [](auto xs) { + static_assert(Iterable<decltype(xs)>{}, ""); + + BOOST_HANA_CONSTANT_CHECK( + hana::is_empty(xs) ^iff^ hana::is_empty(hana::to<tuple_tag>(xs)) + ); + + only_when_(hana::not_(hana::is_empty(xs)), hana::make_lazy([](auto xs) { + BOOST_HANA_CHECK(hana::equal( + hana::front(xs), + hana::front(hana::to<tuple_tag>(xs)) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::to<tuple_tag>(hana::drop_front_exactly(xs)), + hana::drop_front_exactly(hana::to<tuple_tag>(xs)) + )); + + // methods + // back(xs) == at(xs, length(xs)-1) + BOOST_HANA_CHECK(hana::equal( + hana::back(xs), + hana::at(xs, hana::minus(hana::length(xs), hana::size_c<1>)) + )); + + })(xs)); + + // drop_front(xs, 0) == xs + BOOST_HANA_CHECK(hana::equal( + hana::drop_front(xs, size_c<0>), + xs + )); + + // at(xs, n) == front(drop_front(xs, n)) + hana::for_each(hana::make_range(size_c<0>, hana::length(xs)), + hana::capture(xs)([](auto xs, auto n) { + BOOST_HANA_CHECK(hana::equal( + hana::at(xs, n), + hana::front(hana::drop_front(xs, n)) + )); + })); + + // Searchable + hana::eval_if(hana::is_empty(xs), + hana::make_lazy([](auto xs) { + BOOST_HANA_CONSTANT_CHECK( + hana::not_(hana::any_of(xs, hana::always(true_c))) + ); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::find_if(xs, hana::always(true_c)), + nothing + )); + })(xs), + hana::make_lazy([](auto xs) { + BOOST_HANA_CHECK( + hana::any_of(xs, hana::always(true_c)) + ); + BOOST_HANA_CHECK( + hana::not_(hana::any_of(xs, hana::always(false_c))) + ); + + BOOST_HANA_CHECK(hana::equal( + hana::find_if(xs, hana::always(true_c)), + hana::just(hana::front(xs)) + )); + })(xs) + ); + + }); + } + }; + + template <typename S> + struct TestIterable<S, when<Sequence<S>::value>> + : TestIterable<S, laws> + { + template <int i> + using x = ct_eq<i>; + + template <int i = 0> + struct invalid { }; + + struct undefined { }; + + template <typename Xs> + TestIterable(Xs xs) : TestIterable<S, laws>{xs} { + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // front + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + front(list(x<0>{})), + x<0>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + front(list(x<0>{}, invalid<>{})), + x<0>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + front(list(x<0>{}, invalid<1>{}, invalid<2>{})), + x<0>{} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + front(list(1)), 1 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + front(list(1, '2')), 1 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + front(list(1, '2', 3.3)), 1 + )); + + ////////////////////////////////////////////////////////////////// + // back + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + back(list(x<0>{})), + x<0>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + back(list(invalid<0>{}, x<1>{})), + x<1>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + back(list(invalid<0>{}, invalid<1>{}, x<2>{})), + x<2>{} + )); + + BOOST_HANA_CONSTEXPR_CHECK(equal( + back(list(1)), 1 + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + back(list(1, '2')), '2' + )); + BOOST_HANA_CONSTEXPR_CHECK(equal( + back(list(1, '2', 3.3)), 3.3 + )); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_ITERABLE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/logical.hpp b/src/boost/libs/hana/test/_include/laws/logical.hpp new file mode 100644 index 000000000..df9932766 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/logical.hpp @@ -0,0 +1,137 @@ +// 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_LOGICAL_HPP +#define BOOST_HANA_TEST_LAWS_LOGICAL_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/concept/logical.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename L, typename = when<true>> + struct TestLogical : TestLogical<L, laws> { + using TestLogical<L, laws>::TestLogical; + }; + + template <typename L> + struct TestLogical<L, laws> { + template <typename Xs, typename Pred, typename F> + static void for_each_such_that(Xs xs, Pred pred, F f) { + hana::for_each(xs, [&pred, &f](auto x) { + hana::eval_if(pred(x), + hana::make_lazy(f)(x), + [](auto) { } + ); + }); + } + + template <typename Xs> + TestLogical(Xs xs) { + hana::for_each(xs, [](auto x) { + static_assert(Logical<decltype(x)>{}, ""); + }); + + foreach3(xs, hana::capture(xs)([](auto xs, auto a, auto b, auto c) { + auto true_valued = [](auto x) { + return hana::if_(x, true_c, false_c); + }; + auto false_valued = [](auto x) { + return hana::if_(x, false_c, true_c); + }; + + // associativity + BOOST_HANA_CHECK(hana::equal( + hana::or_(a, hana::or_(b, c)), + hana::or_(hana::or_(a, b), c) + )); + BOOST_HANA_CHECK(hana::equal( + hana::and_(a, hana::and_(b, c)), + hana::and_(hana::and_(a, b), c) + )); + + // equivalence through commutativity + BOOST_HANA_CHECK( + hana::or_(a, b) ^iff^ hana::or_(b, a) + ); + BOOST_HANA_CHECK( + hana::and_(a, b) ^iff^ hana::and_(b, a) + ); + + // absorption + BOOST_HANA_CHECK(hana::equal( + hana::or_(a, hana::and_(a, b)), a + )); + BOOST_HANA_CHECK(hana::equal( + hana::and_(a, hana::or_(a, b)), a + )); + + // left identity + TestLogical::for_each_such_that(xs, true_valued, + hana::capture(a)([](auto a, auto t) { + BOOST_HANA_CHECK(hana::equal( + hana::and_(t, a), a + )); + })); + TestLogical::for_each_such_that(xs, false_valued, + hana::capture(a)([](auto a, auto f) { + BOOST_HANA_CHECK(hana::equal( + hana::or_(f, a), a + )); + })); + + // distributivity + BOOST_HANA_CHECK(hana::equal( + hana::or_(a, hana::and_(b, c)), + hana::and_(hana::or_(a, b), hana::or_(a, c)) + )); + BOOST_HANA_CHECK(hana::equal( + hana::and_(a, hana::or_(b, c)), + hana::or_(hana::and_(a, b), hana::and_(a, c)) + )); + + // complements + BOOST_HANA_CHECK(true_valued(hana::or_(a, hana::not_(a)))); + BOOST_HANA_CHECK(false_valued(hana::and_(a, hana::not_(a)))); + + })); + } + }; + + template <typename C> + struct TestLogical<C, when<Constant<C>::value>> + : TestLogical<C, laws> + { + template <typename Xs> + TestLogical(Xs xs) : TestLogical<C, laws>{xs} { + foreach2(xs, [](auto x, auto y) { + + BOOST_HANA_CHECK(hana::equal( + hana::value(hana::not_(x)), + hana::not_(hana::value(x)) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::value(hana::and_(x, y)), + hana::and_(hana::value(x), hana::value(y)) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::value(hana::or_(x, y)), + hana::or_(hana::value(x), hana::value(y)) + )); + + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_LOGICAL_HPP diff --git a/src/boost/libs/hana/test/_include/laws/monad.hpp b/src/boost/libs/hana/test/_include/laws/monad.hpp new file mode 100644 index 000000000..25a23d417 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/monad.hpp @@ -0,0 +1,222 @@ +// 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_HPP +#define BOOST_HANA_TEST_LAWS_MONAD_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/chain.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/monad.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/flatten.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/functional/compose.hpp> +#include <boost/hana/functional/id.hpp> +#include <boost/hana/lift.hpp> +#include <boost/hana/monadic_compose.hpp> +#include <boost/hana/transform.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename M, typename = when<true>> + struct TestMonad : TestMonad<M, laws> { + using TestMonad<M, laws>::TestMonad; + }; + + template <typename M> + struct TestMonad<M, laws> { + // Xs are Monads over something + // XXs are Monads over Monads over something + template <typename Xs, typename XXs> + TestMonad(Xs xs, XXs xxs) { + hana::for_each(xs, [](auto m) { + static_assert(Monad<decltype(m)>{}, ""); + + auto f = hana::compose(lift<M>, test::_injection<0>{}); + auto g = hana::compose(lift<M>, test::_injection<1>{}); + auto h = hana::compose(lift<M>, test::_injection<2>{}); + auto x = test::ct_eq<0>{}; + + ////////////////////////////////////////////////////////////// + // Laws formulated with `monadic_compose` + ////////////////////////////////////////////////////////////// + // associativity + BOOST_HANA_CHECK(hana::equal( + hana::monadic_compose(h, hana::monadic_compose(g, f))(x), + hana::monadic_compose(hana::monadic_compose(h, g), f)(x) + )); + + // left identity + BOOST_HANA_CHECK(hana::equal( + hana::monadic_compose(lift<M>, f)(x), + f(x) + )); + + // right identity + BOOST_HANA_CHECK(hana::equal( + hana::monadic_compose(f, lift<M>)(x), + f(x) + )); + + ////////////////////////////////////////////////////////////// + // Laws formulated with `chain` + // + // This just provides us with some additional cross-checking, + // but the documentation does not mention those. + ////////////////////////////////////////////////////////////// + BOOST_HANA_CHECK(hana::equal( + hana::chain(hana::lift<M>(x), f), + f(x) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::chain(m, lift<M>), + m + )); + + BOOST_HANA_CHECK(hana::equal( + hana::chain(m, [f, g](auto x) { + return hana::chain(f(x), g); + }), + hana::chain(hana::chain(m, f), g) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::transform(m, f), + hana::chain(m, hana::compose(lift<M>, f)) + )); + + ////////////////////////////////////////////////////////////// + // Consistency of method definitions + ////////////////////////////////////////////////////////////// + // consistency of `chain` + BOOST_HANA_CHECK(hana::equal( + hana::chain(m, f), + hana::flatten(hana::transform(m, f)) + )); + + // consistency of `monadic_compose` + BOOST_HANA_CHECK(hana::equal( + hana::monadic_compose(f, g)(x), + hana::chain(g(x), f) + )); + }); + + // consistency of `flatten` + hana::for_each(xxs, [](auto mm) { + BOOST_HANA_CHECK(hana::equal( + hana::flatten(mm), + hana::chain(mm, hana::id) + )); + }); + } + }; + + template <typename S> + struct TestMonad<S, when<Sequence<S>::value>> + : TestMonad<S, laws> + { + template <typename Xs, typename XXs> + TestMonad(Xs xs, XXs xxs) + : TestMonad<S, laws>{xs, xxs} + { + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // flatten + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::flatten(list(list(), list())), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::flatten(list(list(ct_eq<0>{}), list())), + list(ct_eq<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::flatten(list(list(), list(ct_eq<0>{}))), + list(ct_eq<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::flatten(list(list(ct_eq<0>{}), list(ct_eq<1>{}))), + list(ct_eq<0>{}, ct_eq<1>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::flatten(list( + list(ct_eq<0>{}, ct_eq<1>{}), + list(), + list(ct_eq<2>{}, ct_eq<3>{}), + list(ct_eq<4>{}) + )), + list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}) + )); + + // just make sure we don't double move; this happened in hana::tuple + hana::flatten(list(list(Tracked{1}, Tracked{2}))); + + ////////////////////////////////////////////////////////////////// + // chain + ////////////////////////////////////////////////////////////////// + { + test::_injection<0> f{}; + auto g = hana::compose(list, f); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::chain(list(), g), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::chain(list(ct_eq<1>{}), g), + list(f(ct_eq<1>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::chain(list(ct_eq<1>{}, ct_eq<2>{}), g), + list(f(ct_eq<1>{}), f(ct_eq<2>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::chain(list(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}), g), + list(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{})) + )); + + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::chain(list(ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}, ct_eq<4>{}), g), + list(f(ct_eq<1>{}), f(ct_eq<2>{}), f(ct_eq<3>{}), f(ct_eq<4>{})) + )); + } + + ////////////////////////////////////////////////////////////////// + // monadic_compose + ////////////////////////////////////////////////////////////////// + { + test::_injection<0> f{}; + test::_injection<1> g{}; + + auto mf = [=](auto x) { return list(f(x), f(f(x))); }; + auto mg = [=](auto x) { return list(g(x), g(g(x))); }; + + auto x = test::ct_eq<0>{}; + BOOST_HANA_CHECK(hana::equal( + hana::monadic_compose(mf, mg)(x), + list(f(g(x)), f(f(g(x))), f(g(g(x))), f(f(g(g(x))))) + )); + } + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_MONAD_HPP diff --git a/src/boost/libs/hana/test/_include/laws/monad_plus.hpp b/src/boost/libs/hana/test/_include/laws/monad_plus.hpp new file mode 100644 index 000000000..406320c91 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/monad_plus.hpp @@ -0,0 +1,616 @@ +// 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 <boost/hana/append.hpp> +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/chain.hpp> +#include <boost/hana/concat.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/monad_plus.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/cycle.hpp> +#include <boost/hana/empty.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/filter.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/functional/compose.hpp> +#include <boost/hana/integral_constant.hpp> +#include <boost/hana/lift.hpp> +#include <boost/hana/not.hpp> +#include <boost/hana/not_equal.hpp> +#include <boost/hana/prefix.hpp> +#include <boost/hana/prepend.hpp> +#include <boost/hana/remove.hpp> +#include <boost/hana/remove_if.hpp> +#include <boost/hana/replicate.hpp> +#include <boost/hana/suffix.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename M, typename = when<true>> + struct TestMonadPlus : TestMonadPlus<M, laws> { + using TestMonadPlus<M, laws>::TestMonadPlus; + }; + + template <typename M> + struct TestMonadPlus<M, laws> { + template <typename Xs, typename Predicates, typename Values> + TestMonadPlus(Xs xs, Predicates predicates, Values values) { +#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735 + empty<M>(); // force adding empty<M>'s member function to pending temploid list +#endif + + hana::for_each(xs, [](auto a) { + static_assert(MonadPlus<decltype(a)>{}, ""); + + // left identity + BOOST_HANA_CHECK(hana::equal( + hana::concat(hana::empty<M>(), a), + a + )); + + // right identity + BOOST_HANA_CHECK(hana::equal( + hana::concat(a, hana::empty<M>()), + a + )); + + // absorption + auto f = hana::compose(lift<M>, test::_injection<0>{}); + BOOST_HANA_CHECK(hana::equal( + hana::chain(hana::empty<M>(), f), + hana::empty<M>() + )); + + BOOST_HANA_CHECK(hana::equal( + hana::chain(a, hana::always(hana::empty<M>())), + hana::empty<M>() + )); + + }); + + // 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 <typename S> + struct TestMonadPlus<S, when<Sequence<S>::value>> + : TestMonadPlus<S, laws> + { + template <int i> + using eq = test::ct_eq<i>; + + struct undefined { }; + + template <typename Xs, typename Predicates, typename Values> + TestMonadPlus(Xs xs, Predicates predicates, Values values) + : TestMonadPlus<S, laws>{xs, predicates, values} + { + auto z = eq<999>{}; + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // empty + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + hana::empty<S>(), 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<S>(eq<0>{}, size_c<0>), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + replicate<S>(eq<0>{}, size_c<1>), + list(eq<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + replicate<S>(eq<0>{}, size_c<2>), + list(eq<0>{}, eq<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + replicate<S>(eq<0>{}, size_c<3>), + list(eq<0>{}, eq<0>{}, eq<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + replicate<S>(eq<0>{}, size_c<4>), + list(eq<0>{}, eq<0>{}, eq<0>{}, eq<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + replicate<S>(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 diff --git a/src/boost/libs/hana/test/_include/laws/monoid.hpp b/src/boost/libs/hana/test/_include/laws/monoid.hpp new file mode 100644 index 000000000..d500992a0 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/monoid.hpp @@ -0,0 +1,86 @@ +// 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_MONOID_HPP +#define BOOST_HANA_TEST_LAWS_MONOID_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/concept/monoid.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename M, typename = when<true>> + struct TestMonoid : TestMonoid<M, laws> { + using TestMonoid<M, laws>::TestMonoid; + }; + + template <typename M> + struct TestMonoid<M, laws> { + template <typename Xs> + TestMonoid(Xs xs) { +#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735 + zero<M>(); // force adding zero<M>'s member function to pending temploid list +#endif + + hana::for_each(xs, hana::capture(xs)([](auto xs, auto a) { + static_assert(Monoid<decltype(a)>{}, ""); + + // left identity + BOOST_HANA_CHECK(hana::equal( + hana::plus(zero<M>(), a), + a + )); + + // right identity + BOOST_HANA_CHECK(hana::equal( + hana::plus(a, zero<M>()), + a + )); + + hana::for_each(xs, + hana::capture(xs, a)([](auto xs, auto a, auto b) { + hana::for_each(xs, + hana::capture(a, b)([](auto a, auto b, auto c) { + // associativity + BOOST_HANA_CHECK(equal( + hana::plus(a, hana::plus(b, c)), + hana::plus(hana::plus(a, b), c) + )); + })); + })); + + })); + } + }; + + template <typename C> + struct TestMonoid<C, when<Constant<C>::value>> + : TestMonoid<C, laws> + { + template <typename Xs> + TestMonoid(Xs xs) : TestMonoid<C, laws>{xs} { + + BOOST_HANA_CHECK(hana::equal( + hana::value(zero<C>()), + zero<typename C::value_type>() + )); + + foreach2(xs, [](auto x, auto y) { + BOOST_HANA_CHECK(hana::equal( + hana::plus(hana::value(x), hana::value(y)), + hana::value(hana::plus(x, y)) + )); + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_MONOID_HPP diff --git a/src/boost/libs/hana/test/_include/laws/orderable.hpp b/src/boost/libs/hana/test/_include/laws/orderable.hpp new file mode 100644 index 000000000..f49ea7f8a --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/orderable.hpp @@ -0,0 +1,182 @@ +// 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_ORDERABLE_HPP +#define BOOST_HANA_TEST_LAWS_ORDERABLE_HPP + +#include <boost/hana/and.hpp> +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/constant.hpp> +#include <boost/hana/concept/orderable.hpp> +#include <boost/hana/concept/product.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/first.hpp> +#include <boost/hana/greater.hpp> +#include <boost/hana/greater_equal.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/less.hpp> +#include <boost/hana/less_equal.hpp> +#include <boost/hana/not.hpp> +#include <boost/hana/or.hpp> +#include <boost/hana/ordering.hpp> +#include <boost/hana/second.hpp> +#include <boost/hana/value.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename T, typename = when<true>> + struct TestOrderable : TestOrderable<T, laws> { + using TestOrderable<T, laws>::TestOrderable; + }; + + template <typename T> + struct TestOrderable<T, laws> { + template <typename Xs> + TestOrderable(Xs xs) { + hana::for_each(xs, [](auto x) { + static_assert(Orderable<decltype(x)>{}, ""); + }); + + foreach2(xs, [](auto a, auto b) { + + // antisymmetry + BOOST_HANA_CHECK( + hana::and_(hana::less_equal(a, b), hana::less_equal(b, a)) + ^implies^ hana::equal(a, b) + ); + + // totality + BOOST_HANA_CHECK( + hana::or_(hana::less_equal(a, b), hana::less_equal(b, a)) + ); + + // other methods in terms of `less_equal` + BOOST_HANA_CHECK( + hana::less(a, b) ^iff^ hana::not_(hana::less_equal(b, a)) + ); + + BOOST_HANA_CHECK( + hana::greater(a, b) ^iff^ hana::less(b, a) + ); + + BOOST_HANA_CHECK( + hana::greater_equal(a, b) ^iff^ hana::not_(hana::less(a, b)) + ); + + // less.than & al. + BOOST_HANA_CHECK(hana::less.than(a)(b) ^iff^ hana::less(b, a)); + BOOST_HANA_CHECK(hana::greater.than(a)(b) ^iff^ hana::greater(b, a)); + BOOST_HANA_CHECK(hana::less_equal.than(a)(b) ^iff^ hana::less_equal(b, a)); + BOOST_HANA_CHECK(hana::greater_equal.than(a)(b) ^iff^ hana::greater_equal(b, a)); + + // ordering + _injection<0> f{}; // test::_injection is also monotonic + BOOST_HANA_CHECK( + hana::ordering(f)(a, b) ^iff^ hana::less(f(a), f(b)) + ); + }); + + // transitivity + foreach3(xs, [](auto a, auto b, auto c) { + BOOST_HANA_CHECK( + hana::and_(hana::less_equal(a, b), hana::less_equal(b, c)) + ^implies^ hana::less_equal(a, c) + ); + }); + } + }; + + template <typename C> + struct TestOrderable<C, when<Constant<C>::value>> + : TestOrderable<C, laws> + { + template <typename Xs> + TestOrderable(Xs xs) : TestOrderable<C, laws>{xs} { + foreach2(xs, [](auto a, auto b) { + + BOOST_HANA_CHECK( + hana::value(hana::less(a, b)) ^iff^ + hana::less(hana::value(a), hana::value(b)) + ); + + }); + } + }; + + template <typename P> + struct TestOrderable<P, when<Product<P>::value>> + : TestOrderable<P, laws> + { + template <typename Products> + TestOrderable(Products products) + : TestOrderable<P, laws>{products} + { + foreach2(products, [](auto x, auto y) { + BOOST_HANA_CHECK( + hana::less(x, y) ^iff^ + hana::or_( + hana::less(hana::first(x), hana::first(y)), + hana::and_( + hana::equal(hana::first(x), hana::first(y)), + hana::less(hana::second(x), hana::second(y)) + ) + ) + ); + }); + } + }; + + template <typename S> + struct TestOrderable<S, when<Sequence<S>::value>> + : TestOrderable<S, laws> + { + struct invalid { }; + + template <typename Xs> + TestOrderable(Xs xs) : TestOrderable<S, laws>{xs} { + constexpr auto list = make<S>; + + ////////////////////////////////////////////////////////////////// + // less + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less( + list(), + list() + ))); + + BOOST_HANA_CONSTANT_CHECK(hana::less( + list(), + list(invalid{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less( + list(invalid{}), + list() + ))); + BOOST_HANA_CONSTANT_CHECK(hana::less( + list(ct_ord<0>{}), + list(ct_ord<7>{}) + )); + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less( + list(ct_ord<1>{}), + list(ct_ord<0>{}) + ))); + + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::less( + list(ct_ord<0>{}, ct_ord<1>{}, ct_ord<8>{}), + list(ct_ord<0>{}, ct_ord<1>{}) + ))); + + BOOST_HANA_CONSTANT_CHECK(hana::less( + list(ct_ord<0>{}, ct_ord<0>{}, ct_ord<8>{}), + list(ct_ord<0>{}, ct_ord<1>{}) + )); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_ORDERABLE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/product.hpp b/src/boost/libs/hana/test/_include/laws/product.hpp new file mode 100644 index 000000000..18e5a15d2 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/product.hpp @@ -0,0 +1,46 @@ +// 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_PRODUCT_HPP +#define BOOST_HANA_TEST_LAWS_PRODUCT_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/concept/product.hpp> +#include <boost/hana/core/make.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/first.hpp> +#include <boost/hana/second.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename P, typename = when<true>> + struct TestProduct : TestProduct<P, laws> { + using TestProduct<P, laws>::TestProduct; + }; + + template <typename P> + struct TestProduct<P, laws> { + template <typename Elements> + TestProduct(Elements elements) { + foreach2(elements, [](auto x, auto y) { + static_assert(Product<decltype(hana::make<P>(x, y))>{}, ""); + + BOOST_HANA_CHECK(hana::equal( + hana::first(hana::make<P>(x, y)), + x + )); + + BOOST_HANA_CHECK(hana::equal( + hana::second(hana::make<P>(x, y)), + y + )); + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_PRODUCT_HPP diff --git a/src/boost/libs/hana/test/_include/laws/ring.hpp b/src/boost/libs/hana/test/_include/laws/ring.hpp new file mode 100644 index 000000000..4afbca05c --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/ring.hpp @@ -0,0 +1,125 @@ +// 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_RING_HPP +#define BOOST_HANA_TEST_LAWS_RING_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/constant.hpp> +#include <boost/hana/concept/monoid.hpp> +#include <boost/hana/concept/ring.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/mult.hpp> +#include <boost/hana/not_equal.hpp> +#include <boost/hana/one.hpp> +#include <boost/hana/plus.hpp> +#include <boost/hana/power.hpp> +#include <boost/hana/value.hpp> + +#include <laws/base.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename R, typename = when<true>> + struct TestRing : TestRing<R, laws> { + using TestRing<R, laws>::TestRing; + }; + + template <typename R> + struct TestRing<R, laws> { + template <typename Xs> + TestRing(Xs xs) { +#ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735 + one<R>(); // force adding one<R>'s member function to pending temploid list +#endif + + hana::for_each(xs, hana::capture(xs)([](auto xs, auto x) { + static_assert(Ring<decltype(x)>{}, ""); + + foreach2(xs, hana::capture(x)([](auto x, auto y, auto z) { + // associativity + BOOST_HANA_CHECK(hana::equal( + hana::mult(x, hana::mult(y, z)), + hana::mult(hana::mult(x, y), z) + )); + + // distributivity + BOOST_HANA_CHECK(hana::equal( + hana::mult(x, hana::plus(y, z)), + hana::plus(hana::mult(x, y), hana::mult(x, z)) + )); + })); + + // right identity + BOOST_HANA_CHECK(hana::equal( + hana::mult(x, one<R>()), x + )); + + // left identity + BOOST_HANA_CHECK(hana::equal( + hana::mult(one<R>(), x), x + )); + + // power + BOOST_HANA_CHECK(hana::equal( + hana::power(x, int_c<0>), + one<R>() + )); + + BOOST_HANA_CHECK(hana::equal( + hana::power(x, int_c<1>), + x + )); + + BOOST_HANA_CHECK(hana::equal( + hana::power(x, int_c<2>), + hana::mult(x, x) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::power(x, int_c<3>), + hana::mult(hana::mult(x, x), x) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::power(x, int_c<4>), + hana::mult(hana::mult(hana::mult(x, x), x), x) + )); + + BOOST_HANA_CHECK(hana::equal( + hana::power(x, int_c<5>), + hana::mult(hana::mult(hana::mult(hana::mult(x, x), x), x), x) + )); + + })); + } + }; + + template <typename C> + struct TestRing<C, when<Constant<C>::value>> + : TestRing<C, laws> + { + template <typename Xs> + TestRing(Xs xs) : TestRing<C, laws>{xs} { + BOOST_HANA_CHECK(hana::equal( + hana::value(one<C>()), + one<typename C::value_type>() + )); + + foreach2(xs, [](auto x, auto y) { + BOOST_HANA_CHECK(hana::equal( + hana::mult(hana::value(x), hana::value(y)), + hana::value(hana::mult(x, y)) + )); + }); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_RING_HPP diff --git a/src/boost/libs/hana/test/_include/laws/searchable.hpp b/src/boost/libs/hana/test/_include/laws/searchable.hpp new file mode 100644 index 000000000..ae55b06eb --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/searchable.hpp @@ -0,0 +1,611 @@ +// 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_SEARCHABLE_HPP +#define BOOST_HANA_TEST_LAWS_SEARCHABLE_HPP + +#include <boost/hana/all.hpp> +#include <boost/hana/all_of.hpp> +#include <boost/hana/any.hpp> +#include <boost/hana/any_of.hpp> +#include <boost/hana/assert.hpp> +#include <boost/hana/at_key.hpp> +#include <boost/hana/bool.hpp> +#include <boost/hana/concat.hpp> +#include <boost/hana/concept/comparable.hpp> +#include <boost/hana/concept/searchable.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/contains.hpp> +#include <boost/hana/core/is_a.hpp> +#include <boost/hana/core/when.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/find.hpp> +#include <boost/hana/find_if.hpp> +#include <boost/hana/for_each.hpp> +#include <boost/hana/functional/always.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/functional/compose.hpp> +#include <boost/hana/functional/partial.hpp> +#include <boost/hana/is_disjoint.hpp> +#include <boost/hana/is_subset.hpp> +#include <boost/hana/lazy.hpp> +#include <boost/hana/none.hpp> +#include <boost/hana/none_of.hpp> +#include <boost/hana/not.hpp> +#include <boost/hana/optional.hpp> +#include <boost/hana/transform.hpp> +#include <boost/hana/tuple.hpp> + +#include <laws/base.hpp> +#include <support/numeric.hpp> + + +namespace boost { namespace hana { namespace test { + template <typename S, typename = when<true>> + struct TestSearchable : TestSearchable<S, laws> { + using TestSearchable<S, laws>::TestSearchable; + }; + + template <typename S> + struct TestSearchable<S, laws> { + template <typename Searchables, typename Keys> + TestSearchable(Searchables searchables, Keys keys) { + hana::for_each(searchables, [](auto xs) { + static_assert(Searchable<decltype(xs)>{}, ""); + }); + + auto predicates = hana::concat( + hana::to_tuple(hana::transform(keys, equal.to)), + hana::make_tuple( + hana::always(false_c), + hana::always(true_c) + ) + ); + + hana::for_each(searchables, hana::capture(searchables, keys, predicates)( + [](auto searchables, auto keys, auto predicates, auto xs) { + hana::for_each(predicates, hana::capture(xs)( + [](auto xs, auto p) { + // any_of(xs, p) <=> !all_of(xs, negated p) + // <=> !none_of(xs, p) + BOOST_HANA_CHECK( + hana::any_of(xs, p) ^iff^ + hana::not_(hana::all_of(xs, hana::compose(not_, p))) + ); + + BOOST_HANA_CHECK( + hana::any_of(xs, p) ^iff^ + hana::not_(hana::none_of(xs, p)) + ); + })); + + // any(xs) <=> any_of(xs, id) + // all(xs) <=> all_of(xs, id) + // none(xs) <=> none_of(xs, id) + auto all_logicals = hana::all_of(xs, [](auto x) { + return hana::bool_c<hana::Logical<decltype(x)>::value>; + }); + only_when_(all_logicals, hana::make_lazy([](auto xs) { + BOOST_HANA_CHECK( + hana::any(xs) ^iff^ hana::any_of(xs, id) + ); + + BOOST_HANA_CHECK( + hana::all(xs) ^iff^ hana::all_of(xs, hana::id) + ); + + BOOST_HANA_CHECK( + hana::none(xs) ^iff^ hana::none_of(xs, hana::id) + ); + })(xs)); + + // find_if(xs, always(false_c)) == nothing + BOOST_HANA_CONSTANT_CHECK(hana::equal( + hana::find_if(xs, hana::always(hana::false_c)), + hana::nothing + )); + + hana::for_each(searchables, hana::capture(xs)([](auto xs, auto ys) { + // is_subset(xs, ys) <=> all_of(xs, [](auto x) { return contains(ys, x); }) + BOOST_HANA_CHECK( + hana::is_subset(xs, ys) ^iff^ + hana::all_of(xs, hana::partial(hana::contains, ys)) + ); + + // is_disjoint(xs, ys) <=> none_of(xs, [](auto x) { return contains(ys, x); }) + BOOST_HANA_CHECK( + hana::is_disjoint(xs, ys) ^iff^ + hana::none_of(xs, hana::partial(hana::contains, ys)) + ); + })); + + hana::for_each(keys, hana::capture(xs)([](auto xs, auto key) { + // find(xs, x) == find_if(xs, [](auto y) { return y == x; }) + BOOST_HANA_CHECK(hana::equal( + hana::find(xs, key), + hana::find_if(xs, hana::equal.to(key)) + )); + + // contains(xs, x) <=> any_of(xs, [](auto y) { return y == x; }) + BOOST_HANA_CHECK( + hana::contains(xs, key) ^iff^ + hana::any_of(xs, hana::equal.to(key)) + ); + + only_when_(hana::contains(xs, key), + hana::make_lazy([](auto xs, auto key) { + // at_key(xs, key) == find(xs, key).value() + BOOST_HANA_CHECK(hana::equal( + hana::at_key(xs, key), + hana::find(xs, key).value() + )); + })(xs, key) + ); + })); + })); + } + }; + + template <typename S> + struct TestSearchable<S, when<Sequence<S>::value>> + : TestSearchable<S, laws> + { + template <int i> + using x = _constant<i>; + + template <int = 0> + struct invalid { }; + + struct undefined { }; + + template <typename Xs, typename Keys> + TestSearchable(Xs xs, Keys keys) + : TestSearchable<S, laws>{xs, keys} + { + constexpr auto list = make<S>; + + BOOST_HANA_CONSTEXPR_LAMBDA auto is_even = [](auto x) { + return x % 2 == 0; + }; + + auto c = numeric; // a minimal comparable + auto logical = numeric; + + ////////////////////////////////////////////////////////////////// + // any_of + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK( + hana::not_(hana::any_of(list(), equal.to(x<9>{}))) + ); + + BOOST_HANA_CONSTANT_CHECK( + hana::not_(hana::any_of(list(x<0>{}), equal.to(x<9>{}))) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}), equal.to(x<0>{})) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, invalid<1>{}), equal.to(x<0>{})) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, invalid<1>{}, invalid<2>{}), equal.to(x<0>{})) + ); + + BOOST_HANA_CONSTANT_CHECK( + hana::not_(hana::any_of(list(x<0>{}, x<1>{}), equal.to(x<9>{}))) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, x<1>{}), equal.to(x<1>{})) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, x<1>{}, invalid<2>{}), equal.to(x<1>{})) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), equal.to(x<1>{})) + ); + + BOOST_HANA_CONSTANT_CHECK( + hana::not_(hana::any_of(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<9>{}))) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<2>{})) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, x<1>{}, x<2>{}, nothing), equal.to(x<2>{})) + ); + BOOST_HANA_CONSTANT_CHECK( + hana::any_of(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), equal.to(x<2>{})) + ); + + BOOST_HANA_CONSTANT_CHECK( + hana::not_(hana::any_of(list(), invalid<>{})) + ); + + + BOOST_HANA_CONSTEXPR_CHECK( + hana::any_of(list(c(0)), equal.to(c(0))) + ); + BOOST_HANA_CONSTEXPR_CHECK( + hana::not_(hana::any_of(list(c(0)), equal.to(c(1)))) + ); + BOOST_HANA_CONSTEXPR_CHECK( + hana::not_(hana::any_of(list(1), is_even)) + ); + BOOST_HANA_CONSTEXPR_CHECK( + hana::any_of(list(2), is_even) + ); + BOOST_HANA_CONSTEXPR_CHECK( + hana::any_of(list(1, 2), is_even) + ); + BOOST_HANA_CONSTEXPR_CHECK( + hana::not_(hana::any_of(list(1, 3), is_even)) + ); + BOOST_HANA_CONSTEXPR_CHECK( + hana::any_of(list(1, 3, 4), is_even) + ); + + ////////////////////////////////////////////////////////////////// + // any + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::any(list()))); + BOOST_HANA_CONSTEXPR_CHECK(hana::any(list(logical(true)))); + BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::any(list(logical(false))))); + + + ////////////////////////////////////////////////////////////////// + // all_of + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK( + all_of(list(), invalid<>{}) + ); + BOOST_HANA_CONSTEXPR_CHECK( + all_of(list(c(0)), equal.to(c(0))) + ); + BOOST_HANA_CONSTEXPR_CHECK( + not_(all_of(list(c(0)), equal.to(c(1)))) + ); + BOOST_HANA_CONSTEXPR_CHECK(not_( + all_of(list(c(0), c(1)), equal.to(c(0))) + )); + BOOST_HANA_CONSTEXPR_CHECK( + all_of(list(c(0), c(0)), equal.to(c(0))) + ); + + BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1), is_even))); + BOOST_HANA_CONSTEXPR_CHECK(all_of(list(2), is_even)); + BOOST_HANA_CONSTEXPR_CHECK(all_of(list(2, 4), is_even)); + BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 2), is_even))); + BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 3), is_even))); + BOOST_HANA_CONSTEXPR_CHECK(not_(all_of(list(1, 3, 4), is_even))); + + + ////////////////////////////////////////////////////////////////// + // all + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(all(list())); + BOOST_HANA_CONSTEXPR_CHECK(all(list(logical(true)))); + BOOST_HANA_CONSTEXPR_CHECK(not_(all(list(logical(false))))); + BOOST_HANA_CONSTEXPR_CHECK(all(list(logical(true), logical(true)))); + BOOST_HANA_CONSTEXPR_CHECK(not_(all(list(logical(true), logical(false))))); + + ////////////////////////////////////////////////////////////////// + // none_of + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(none_of(list(), invalid<>{})); + BOOST_HANA_CONSTEXPR_CHECK(none_of(list(c(0)), equal.to(c(1)))); + BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(c(0)), equal.to(c(0))))); + + BOOST_HANA_CONSTEXPR_CHECK(none_of(list(1), is_even)); + BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(2), is_even))); + BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(1, 2), is_even))); + BOOST_HANA_CONSTEXPR_CHECK(none_of(list(1, 3), is_even)); + BOOST_HANA_CONSTEXPR_CHECK(not_(none_of(list(1, 3, 4), is_even))); + + + ////////////////////////////////////////////////////////////////// + // none + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(none(list())); + BOOST_HANA_CONSTEXPR_CHECK(none(list(logical(false)))); + BOOST_HANA_CONSTEXPR_CHECK(not_(none(list(logical(true))))); + + ////////////////////////////////////////////////////////////////// + // find_if + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(), equal.to(x<9>{})), + nothing + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}), equal.to(x<9>{})), + nothing + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}), equal.to(x<0>{})), + just(x<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, invalid<1>{}), equal.to(x<0>{})), + just(x<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, invalid<1>{}, invalid<2>{}), equal.to(x<0>{})), + just(x<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}), equal.to(x<9>{})), + nothing + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}), equal.to(x<1>{})), + just(x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}, invalid<2>{}), equal.to(x<1>{})), + just(x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), equal.to(x<1>{})), + just(x<1>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<9>{})), + nothing + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}, x<2>{}), equal.to(x<2>{})), + just(x<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}, x<2>{}, nothing), equal.to(x<2>{})), + just(x<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), equal.to(x<2>{})), + just(x<2>{}) + )); + + // Make sure find_if works with an lvalue sequence. hana::tuple + // used to have a bug that broke this. + auto const const_lvalue = list(x<0>{}, x<1>{}, x<2>{}); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(const_lvalue, equal.to(x<1>{})), + just(x<1>{}) + )); + + auto lvalue = list(x<0>{}, x<1>{}, x<2>{}); + BOOST_HANA_CONSTANT_CHECK(equal( + find_if(lvalue, equal.to(x<1>{})), + just(x<1>{}) + )); + } + + ////////////////////////////////////////////////////////////////// + // find + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(), invalid<>{}), + nothing + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}), x<9>{}), + nothing + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}), x<0>{}), + just(x<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, invalid<1>{}), x<0>{}), + just(x<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, invalid<1>{}, invalid<2>{}), x<0>{}), + just(x<0>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}), x<9>{}), + nothing + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}), x<1>{}), + just(x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}, invalid<2>{}), x<1>{}), + just(x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}, invalid<2>{}, invalid<3>{}), x<1>{}), + just(x<1>{}) + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}, x<2>{}), x<9>{}), + nothing + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}, x<2>{}), x<2>{}), + just(x<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}, x<2>{}, nothing), x<2>{}), + just(x<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + find(list(x<0>{}, x<1>{}, x<2>{}, nothing, nothing), x<2>{}), + just(x<2>{}) + )); + } + + ////////////////////////////////////////////////////////////////// + // at_key + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(equal( + at_key(list(x<0>{}), x<0>{}), + x<0>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + at_key(list(x<0>{}, x<1>{}), x<0>{}), + x<0>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + at_key(list(x<0>{}, x<1>{}), x<1>{}), + x<1>{} + )); + + BOOST_HANA_CONSTANT_CHECK(equal( + at_key(list(x<0>{}, x<1>{}, x<2>{}), x<0>{}), + x<0>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + at_key(list(x<0>{}, x<1>{}, x<2>{}), x<1>{}), + x<1>{} + )); + BOOST_HANA_CONSTANT_CHECK(equal( + at_key(list(x<0>{}, x<1>{}, x<2>{}), x<2>{}), + x<2>{} + )); + } + + ////////////////////////////////////////////////////////////////// + // contains + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(not_( + contains(list(), undefined{}) + )); + + BOOST_HANA_CONSTANT_CHECK(not_( + contains(list(x<0>{}), x<999>{}) + )); + + BOOST_HANA_CONSTANT_CHECK( + contains(list(x<0>{}), x<0>{}) + ); + + BOOST_HANA_CONSTANT_CHECK( + contains(list(x<0>{}, x<1>{}), x<1>{}) + ); + + BOOST_HANA_CONSTANT_CHECK( + contains(list(x<0>{}, x<1>{}, x<3>{}), x<3>{}) + ); + + BOOST_HANA_CONSTEXPR_CHECK(contains(list(c(0)), c(0))); + BOOST_HANA_CONSTEXPR_CHECK(not_(contains(list(c(0)), c(1)))); + + // infix application + BOOST_HANA_CONSTANT_CHECK( + list(x<0>{}, x<1>{}) ^contains^ x<1>{} + ); + } + + ////////////////////////////////////////////////////////////////// + // in + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTEXPR_CHECK(c(0) ^in^ list(c(0))); + BOOST_HANA_CONSTEXPR_CHECK(not_(c(1) ^in^ list(c(0)))); + + ////////////////////////////////////////////////////////////////// + // is_subset + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(is_subset( + list(), list(undefined{}) + )); + + BOOST_HANA_CONSTANT_CHECK(not_(is_subset( + list(undefined{}), list() + ))); + + BOOST_HANA_CONSTEXPR_CHECK(is_subset( + list(c(0)), list(c(0)) + )); + + BOOST_HANA_CONSTEXPR_CHECK(is_subset( + list(c(0)), list(c(0), c(1)) + )); + + BOOST_HANA_CONSTEXPR_CHECK(not_(is_subset( + list(c(0)), list(c(1)) + ))); + + // infix application + BOOST_HANA_CONSTANT_CHECK( + list(x<0>{}) ^is_subset^ list(x<1>{}, x<0>{}) + ); + + BOOST_HANA_CONSTANT_CHECK( + list(x<0>{}, x<1>{}) ^is_subset^ list(x<1>{}, x<0>{}) + ); + } + + ////////////////////////////////////////////////////////////////// + // is_disjoint + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(is_disjoint( + list(), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(is_disjoint( + list(), + list(undefined{}) + )); + BOOST_HANA_CONSTANT_CHECK(is_disjoint( + list(undefined{}), + list() + )); + + BOOST_HANA_CONSTANT_CHECK(is_disjoint( + list(x<0>{}), + list(x<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(is_disjoint( + list(x<1>{}), + list(x<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint( + list(x<0>{}), + list(x<0>{}) + ))); + + + BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint( + list(x<0>{}, x<1>{}), + list(x<0>{}) + ))); + BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint( + list(x<0>{}), + list(x<0>{}, x<1>{}) + ))); + BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint( + list(x<1>{}, x<0>{}), + list(x<0>{}, x<1>{}) + ))); + BOOST_HANA_CONSTANT_CHECK(not_(is_disjoint( + list(x<0>{}, x<1>{}), + list(x<1>{}, x<2>{}) + ))); + BOOST_HANA_CONSTANT_CHECK(is_disjoint( + list(x<0>{}, x<1>{}), + list(x<2>{}, x<3>{}) + )); + } + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_SEARCHABLE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/sequence.hpp b/src/boost/libs/hana/test/_include/laws/sequence.hpp new file mode 100644 index 000000000..cc04590ea --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/sequence.hpp @@ -0,0 +1,133 @@ +// 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_SEQUENCE_HPP +#define BOOST_HANA_TEST_LAWS_SEQUENCE_HPP + +#include <boost/hana/assert.hpp> +#include <boost/hana/concept/sequence.hpp> +#include <boost/hana/config.hpp> +#include <boost/hana/core/tag_of.hpp> +#include <boost/hana/functional/capture.hpp> +#include <boost/hana/functional/compose.hpp> +#include <boost/hana/functional/id.hpp> +#include <boost/hana/functional/partial.hpp> +#include <boost/hana/integral_constant.hpp> +#include <boost/hana/optional.hpp> +#include <boost/hana/plus.hpp> +#include <boost/hana/range.hpp> +#include <boost/hana/tuple.hpp> + +#include <laws/base.hpp> +#include <support/minimal_product.hpp> +#include <support/seq.hpp> + +#include <type_traits> +#include <vector> + + +namespace boost { namespace hana { namespace test { + template <typename S, typename = when<true>> + struct TestSequence : TestSequence<S, laws> { + using TestSequence<S, laws>::TestSequence; + }; + + template <typename S> + struct TestSequence<S, laws> { + template <int i> + using eq = integer<i, + Policy::Comparable + | Policy::Constant + >; + + template <int i> + using cx_eq = integer<i, + Policy::Comparable + | Policy::Constexpr + >; + + template <int i> + using ord = integer<i, + Policy::Orderable + | Policy::Constant + >; + + struct undefined { }; + + TestSequence() { + constexpr auto list = make<S>; (void)list; + constexpr auto foldable = ::seq; (void)foldable; + + ////////////////////////////////////////////////////////////////// + // Check for Sequence<...> + ////////////////////////////////////////////////////////////////// + static_assert(Sequence<decltype(list())>{}, ""); + static_assert(Sequence<decltype(list(1))>{}, ""); + static_assert(Sequence<decltype(list(1, '2'))>{}, ""); + static_assert(Sequence<decltype(list(1, '2', 3.4))>{}, ""); + + ////////////////////////////////////////////////////////////////// + // Check for basic tag consistency + ////////////////////////////////////////////////////////////////// + struct Random; + static_assert(std::is_same<tag_of_t<decltype(list())>, S>{}, ""); + static_assert(std::is_same<tag_of_t<decltype(list(1))>, S>{}, ""); + static_assert(std::is_same<tag_of_t<decltype(list(1, '2'))>, S>{}, ""); + static_assert(std::is_same<tag_of_t<decltype(list(1, '2', 3.3))>, S>{}, ""); + static_assert(!std::is_same<tag_of_t<Random>, S>{}, ""); + + ////////////////////////////////////////////////////////////////// + // Foldable -> Sequence conversion + ////////////////////////////////////////////////////////////////// + { + BOOST_HANA_CONSTANT_CHECK(equal( + to<S>(foldable()), + list() + )); + BOOST_HANA_CONSTANT_CHECK(equal( + to<S>(foldable(eq<0>{})), + list(eq<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + to<S>(foldable(eq<0>{}, eq<1>{})), + list(eq<0>{}, eq<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + to<S>(foldable(eq<0>{}, eq<1>{}, eq<2>{})), + list(eq<0>{}, eq<1>{}, eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + to<S>(foldable(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{})), + list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}) + )); + } + + ////////////////////////////////////////////////////////////////// + // make (tautological given our definition of `list`) + ////////////////////////////////////////////////////////////////// + BOOST_HANA_CONSTANT_CHECK(equal( + make<S>(), + list() + )); + BOOST_HANA_CONSTANT_CHECK(equal( + make<S>(eq<0>{}), + list(eq<0>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + make<S>(eq<0>{}, eq<1>{}), + list(eq<0>{}, eq<1>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + make<S>(eq<0>{}, eq<1>{}, eq<2>{}), + list(eq<0>{}, eq<1>{}, eq<2>{}) + )); + BOOST_HANA_CONSTANT_CHECK(equal( + make<S>(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}), + list(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}) + )); + } + }; +}}} // end namespace boost::hana::test + +#endif // !BOOST_HANA_TEST_LAWS_SEQUENCE_HPP diff --git a/src/boost/libs/hana/test/_include/laws/templates/seq.hpp b/src/boost/libs/hana/test/_include/laws/templates/seq.hpp new file mode 100644 index 000000000..72438fc50 --- /dev/null +++ b/src/boost/libs/hana/test/_include/laws/templates/seq.hpp @@ -0,0 +1,132 @@ +// 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) + +#include <boost/hana/bool.hpp> +#include <boost/hana/equal.hpp> +#include <boost/hana/functional/always.hpp> +#include <boost/hana/tuple.hpp> + +#include <laws/applicative.hpp> +#include <laws/base.hpp> +#include <laws/comparable.hpp> +#include <laws/foldable.hpp> +#include <laws/functor.hpp> +#include <laws/iterable.hpp> +#include <laws/monad.hpp> +#include <laws/monad_plus.hpp> +#include <laws/orderable.hpp> +#include <laws/searchable.hpp> +#include <laws/sequence.hpp> +#include <support/seq.hpp> +namespace hana = boost::hana; +using hana::test::ct_eq; +using hana::test::ct_ord; + + +int main() { + auto eqs = hana::make_tuple( + ::seq() + , ::seq(ct_eq<0>{}) + , ::seq(ct_eq<0>{}, ct_eq<1>{}) + , ::seq(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}) + , ::seq(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}, ct_eq<3>{}) + ); + (void)eqs; + + auto nested_eqs = hana::make_tuple( + ::seq() + , ::seq( + ::seq(ct_eq<0>{})) + , ::seq( + ::seq(ct_eq<0>{}), + ::seq(ct_eq<1>{}, ct_eq<2>{})) + , ::seq( + ::seq(ct_eq<0>{}), + ::seq(ct_eq<1>{}, ct_eq<2>{}), + ::seq(ct_eq<3>{}, ct_eq<4>{})) + ); + (void)nested_eqs; + + auto eq_keys = hana::make_tuple(ct_eq<0>{}, ct_eq<3>{}, ct_eq<10>{}); + (void)eq_keys; + + auto predicates = hana::make_tuple( + hana::equal.to(ct_eq<0>{}), hana::equal.to(ct_eq<3>{}), hana::equal.to(ct_eq<10>{}), + hana::always(hana::true_c), hana::always(hana::false_c) + ); + (void)predicates; + + auto ords = hana::make_tuple( + ::seq() + , ::seq(ct_ord<0>{}) + , ::seq(ct_ord<0>{}, ct_ord<1>{}) + , ::seq(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}) + , ::seq(ct_ord<0>{}, ct_ord<1>{}, ct_ord<2>{}, ct_ord<3>{}) + ); + (void)ords; + + ////////////////////////////////////////////////////////////////////////// + // Comparable, Orderable + ////////////////////////////////////////////////////////////////////////// +#ifdef BOOST_HANA_TEST_ORDERABLE + hana::test::TestComparable<::Seq>{eqs}; + hana::test::TestOrderable<::Seq>{ords}; +#endif + +#ifdef BOOST_HANA_TEST_ITERABLE + ////////////////////////////////////////////////////////////////////////// + // Foldable + ////////////////////////////////////////////////////////////////////////// + hana::test::TestFoldable<::Seq>{eqs}; + + ////////////////////////////////////////////////////////////////////////// + // Iterable + ////////////////////////////////////////////////////////////////////////// + { + hana::test::TestIterable<::Seq>{eqs}; + } +#endif + + ////////////////////////////////////////////////////////////////////////// + // Searchable + ////////////////////////////////////////////////////////////////////////// +#ifdef BOOST_HANA_TEST_SEARCHABLE + { + hana::test::TestSearchable<::Seq>{eqs, eq_keys}; + + auto bools = hana::make_tuple( + ::seq(hana::true_c) + , ::seq(hana::false_c) + , ::seq(hana::true_c, hana::true_c) + , ::seq(hana::true_c, hana::false_c) + , ::seq(hana::false_c, hana::true_c) + , ::seq(hana::false_c, hana::false_c) + ); + hana::test::TestSearchable<::Seq>{bools, hana::make_tuple(hana::true_c, hana::false_c)}; + } +#endif + + ////////////////////////////////////////////////////////////////////////// + // Functor, Applicative, Monad + ////////////////////////////////////////////////////////////////////////// +#ifdef BOOST_HANA_TEST_MONAD + hana::test::TestFunctor<::Seq>{eqs, eq_keys}; + hana::test::TestApplicative<::Seq>{eqs}; + hana::test::TestMonad<::Seq>{eqs, nested_eqs}; +#endif + + ////////////////////////////////////////////////////////////////////////// + // MonadPlus + ////////////////////////////////////////////////////////////////////////// +#ifdef BOOST_HANA_TEST_MONAD_PLUS + hana::test::TestMonadPlus<::Seq>{eqs, predicates, eq_keys}; +#endif + + ////////////////////////////////////////////////////////////////////////// + // Sequence + ////////////////////////////////////////////////////////////////////////// +#ifdef BOOST_HANA_TEST_SEQUENCE + hana::test::TestSequence<::Seq>{}; +#endif +} |