2
0
mirror of https://github.com/boostorg/hana.git synced 2026-02-01 20:42:13 +00:00
Files
hana/test/either.cpp
2015-04-10 13:17:51 -04:00

360 lines
9.9 KiB
C++

/*
@copyright Louis Dionne 2015
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/either.hpp>
#include <boost/hana/assert.hpp>
#include <boost/hana/core/datatype.hpp>
#include <boost/hana/functional/compose.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/monad.hpp>
#include <laws/orderable.hpp>
#include <laws/traversable.hpp>
#include <test/identity.hpp>
#include <type_traits>
using namespace boost::hana;
using test::ct_eq;
using test::ct_ord;
struct undefined { };
int main() {
auto eqs = make<Tuple>(
right(ct_eq<0>{}), left(ct_eq<0>{}),
right(ct_eq<2>{}), left(ct_eq<2>{}),
right(ct_eq<3>{}), left(ct_eq<3>{})
);
(void)eqs;
auto big_eqs = make<Tuple>(
right(ct_eq<0>{}), left(ct_eq<0>{}),
right(ct_eq<1>{}), left(ct_eq<1>{}),
right(ct_eq<2>{}), left(ct_eq<2>{}),
right(ct_eq<3>{}), left(ct_eq<3>{})
);
(void)big_eqs;
auto eq_keys = make<Tuple>(ct_eq<0>{}, ct_eq<2>{});
(void)eq_keys;
auto nested_eqs = make<Tuple>(
right(right(ct_eq<2>{})), left(right(ct_eq<2>{})),
right(right(ct_eq<3>{})), left(right(ct_eq<3>{})),
right(left(ct_eq<0>{})), left(left(ct_eq<0>{})),
right(left(ct_eq<1>{})), left(left(ct_eq<1>{}))
);
(void)nested_eqs;
auto ords = make<Tuple>(
right(ct_ord<0>{}), left(ct_ord<0>{}),
right(ct_ord<2>{}), left(ct_ord<2>{}),
right(ct_ord<3>{}), left(ct_ord<3>{})
);
(void)ords;
#if BOOST_HANA_TEST_PART == 1
//////////////////////////////////////////////////////////////////////////
// Interface
//////////////////////////////////////////////////////////////////////////
{
test::_injection<0> f{};
test::_injection<0> g{};
// left
{
auto e = left(undefined{});
static_assert(std::is_same<
datatype_t<decltype(e)>, Either
>::value, "");
}
// right
{
auto e = right(undefined{});
static_assert(std::is_same<
datatype_t<decltype(e)>, Either
>::value, "");
}
// either
{
BOOST_HANA_CONSTANT_CHECK(equal(
either(f, g, left(ct_eq<0>{})),
f(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(equal(
either(f, g, right(ct_eq<0>{})),
g(ct_eq<0>{})
));
}
// Make sure we do not instantiate rogue contructors when trying
// to copy an Either.
{
{
auto expr = right(test::trap_construct{});
auto implicit_copy = expr; (void)implicit_copy;
decltype(expr) explicit_copy(expr); (void)explicit_copy;
}
{
auto expr = left(test::trap_construct{});
auto implicit_copy = expr; (void)implicit_copy;
decltype(expr) explicit_copy(expr); (void)explicit_copy;
}
}
// implicit and explicit construction of left and right
{
_right<int> r1{1}; (void)r1;
_right<int> r2 = {1}; (void)r2;
_left<int> l1{1}; (void)l1;
_left<int> l2 = {1}; (void)l2;
}
}
//////////////////////////////////////////////////////////////////////////
// Comparable
//////////////////////////////////////////////////////////////////////////
{
// equal
{
BOOST_HANA_CONSTANT_CHECK(equal(
left(ct_eq<0>{}),
left(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(not_(equal(
left(ct_eq<0>{}),
left(ct_eq<1>{})
)));
BOOST_HANA_CONSTANT_CHECK(not_(equal(
left(undefined{}),
right(undefined{})
)));
BOOST_HANA_CONSTANT_CHECK(not_(equal(
right(undefined{}),
left(undefined{})
)));
BOOST_HANA_CONSTANT_CHECK(equal(
right(ct_eq<0>{}),
right(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(not_(equal(
right(ct_eq<0>{}),
right(ct_eq<1>{})
)));
}
// laws
test::TestComparable<Either>{eqs};
}
#elif BOOST_HANA_TEST_PART == 2
//////////////////////////////////////////////////////////////////////////
// Orderable
//////////////////////////////////////////////////////////////////////////
{
// less
{
BOOST_HANA_CONSTANT_CHECK(less(
left(ct_ord<0>{}),
left(ct_ord<1>{})
));
BOOST_HANA_CONSTANT_CHECK(not_(less(
left(ct_ord<0>{}),
left(ct_ord<0>{})
)));
BOOST_HANA_CONSTANT_CHECK(not_(less(
left(ct_ord<1>{}),
left(ct_ord<0>{})
)));
BOOST_HANA_CONSTANT_CHECK(less(
right(ct_ord<0>{}),
right(ct_ord<1>{})
));
BOOST_HANA_CONSTANT_CHECK(not_(less(
right(ct_ord<0>{}),
right(ct_ord<0>{})
)));
BOOST_HANA_CONSTANT_CHECK(not_(less(
right(ct_ord<1>{}),
right(ct_ord<0>{})
)));
BOOST_HANA_CONSTANT_CHECK(less(
left(ct_ord<0>{}),
right(ct_ord<1>{})
));
BOOST_HANA_CONSTANT_CHECK(less(
left(ct_ord<0>{}),
right(ct_ord<0>{})
));
BOOST_HANA_CONSTANT_CHECK(less(
left(ct_ord<1>{}),
right(ct_ord<0>{})
));
}
// laws
test::TestOrderable<Either>{ords};
}
#elif BOOST_HANA_TEST_PART == 3
//////////////////////////////////////////////////////////////////////////
// Foldable
//////////////////////////////////////////////////////////////////////////
{
// unpack
{
test::_injection<0> f{};
BOOST_HANA_CONSTANT_CHECK(equal(
unpack(left(ct_eq<0>{}), f),
f()
));
BOOST_HANA_CONSTANT_CHECK(equal(
unpack(right(ct_eq<0>{}), f),
f(ct_eq<0>{})
));
}
// laws
test::TestFoldable<Either>{big_eqs};
}
//////////////////////////////////////////////////////////////////////////
// Traversable
//////////////////////////////////////////////////////////////////////////
{
test::_injection<0> f{};
auto f_ = compose(lift<test::Identity>, f);
BOOST_HANA_CONSTANT_CHECK(equal(
traverse<test::Identity>(left(ct_eq<0>{}), f_),
test::identity(left(ct_eq<0>{}))
));
BOOST_HANA_CONSTANT_CHECK(equal(
traverse<test::Identity>(right(ct_eq<0>{}), f_),
test::identity(right(f(ct_eq<0>{})))
));
// laws
test::TestTraversable<Either>{};
}
#elif BOOST_HANA_TEST_PART == 4
//////////////////////////////////////////////////////////////////////////
// Functor
//////////////////////////////////////////////////////////////////////////
{
// transform
{
test::_injection<0> f{};
BOOST_HANA_CONSTANT_CHECK(equal(
transform(left(ct_eq<0>{}), undefined{}),
left(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(equal(
transform(right(ct_eq<0>{}), f),
right(f(ct_eq<0>{}))
));
}
// laws
test::TestFunctor<Either>{big_eqs, eq_keys};
}
//////////////////////////////////////////////////////////////////////////
// Applicative
//////////////////////////////////////////////////////////////////////////
{
test::_injection<0> f{};
// ap
{
BOOST_HANA_CONSTANT_CHECK(equal(
ap(left(ct_eq<0>{}), left(undefined{})),
left(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(equal(
ap(left(ct_eq<0>{}), right(undefined{})),
left(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(equal(
ap(right(undefined{}), left(ct_eq<0>{})),
left(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(equal(
ap(right(f), right(ct_eq<0>{})),
right(f(ct_eq<0>{}))
));
}
// lift
{
BOOST_HANA_CONSTANT_CHECK(equal(
lift<Either>(ct_eq<0>{}),
right(ct_eq<0>{})
));
}
// laws
test::TestApplicative<Either>{eqs};
}
#elif BOOST_HANA_TEST_PART == 5
//////////////////////////////////////////////////////////////////////////
// Monad
//////////////////////////////////////////////////////////////////////////
{
// flatten
{
BOOST_HANA_CONSTANT_CHECK(equal(
flatten(left(left(ct_eq<0>{}))),
left(left(ct_eq<0>{}))
));
BOOST_HANA_CONSTANT_CHECK(equal(
flatten(left(right(ct_eq<0>{}))),
left(right(ct_eq<0>{}))
));
BOOST_HANA_CONSTANT_CHECK(equal(
flatten(right(left(ct_eq<0>{}))),
left(ct_eq<0>{})
));
BOOST_HANA_CONSTANT_CHECK(equal(
flatten(right(right(ct_eq<0>{}))),
right(ct_eq<0>{})
));
}
// laws
test::TestMonad<Either>{big_eqs, nested_eqs};
}
#endif
}