hana/test/_include/laws/constant.hpp
2017-01-07 14:14:18 -08:00

107 lines
3.8 KiB
C++

// 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