/* @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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace boost::hana; template using eq = test::ct_eq; template using ord = test::ct_ord; struct x0; struct x1; struct x2; struct x3; struct x4; template struct F { struct type; }; int main() { auto eq_tuples = make( make() , make(eq<0>{}) , make(eq<0>{}, eq<1>{}) , make(eq<0>{}, eq<1>{}, eq<2>{}) , make(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}) , make(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}) , make(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}, eq<5>{}) ); (void)eq_tuples; auto eq_values = make(eq<0>{}, eq<2>{}, eq<4>{}); (void)eq_values; auto predicates = make( equal.to(eq<0>{}), equal.to(eq<2>{}), equal.to(eq<4>{}), always(true_), always(false_) ); (void)predicates; auto ord_tuples = make( make() , make(ord<0>{}) , make(ord<0>{}, ord<1>{}) , make(ord<0>{}, ord<1>{}, ord<2>{}) , make(ord<0>{}, ord<1>{}, ord<2>{}, ord<3>{}) , make(ord<0>{}, ord<1>{}, ord<2>{}, ord<3>{}, ord<4>{}) ); (void)ord_tuples; auto nested_eqs = make( make() , make(make(eq<0>{})) , make(make(eq<0>{}), make(eq<1>{}, eq<2>{})) , make(make(eq<0>{}), make(eq<1>{}, eq<2>{}), make(eq<3>{}, eq<4>{})) ); (void)nested_eqs; #if BOOST_HANA_TEST_PART == 1 ////////////////////////////////////////////////////////////////////////// // Move-only friendliness and reference semantics ////////////////////////////////////////////////////////////////////////// { { auto xs = make(test::move_only{}); auto by_val = [](auto) { }; by_val(std::move(xs)); by_val(head(std::move(xs))); by_val(at_c<0>(std::move(xs))); by_val(last(std::move(xs))); } { auto const& xs = make(test::move_only{}); auto by_const_ref = [](auto const&) { }; by_const_ref(xs); by_const_ref(head(xs)); by_const_ref(at_c<0>(xs)); by_const_ref(last(xs)); } { auto xs = make(test::move_only{}); auto by_ref = [](auto&) { }; by_ref(xs); by_ref(head(xs)); by_ref(at_c<0>(xs)); by_ref(last(xs)); } } ////////////////////////////////////////////////////////////////////////// // default-constructibility ////////////////////////////////////////////////////////////////////////// { _tuple<> z1{}; (void)z1; _tuple z2{}; (void)z2; _tuple z3{}; (void)z3; _tuple z4{}; (void)z4; using Types = decltype(tuple_t); Types default_{}; (void)default_; } ////////////////////////////////////////////////////////////////////////// // In some cases where a type has a constructor that is way too // general, copying a unary tuple holding an object of that type // could trigger the instantiation of that constructor. If that // constructor was ill-formed, the compilation could fail. We // make sure this does not happen. ////////////////////////////////////////////////////////////////////////// { auto expr = make(test::trap_construct{}); auto implicit_copy = expr; (void)implicit_copy; decltype(expr) explicit_copy(expr); (void)explicit_copy; } ////////////////////////////////////////////////////////////////////////// // This used to trigger an ICE on Clang ////////////////////////////////////////////////////////////////////////// { struct Car { std::string name; }; auto stuff = make(Car{}, Car{}, Car{}); any_of(stuff, [](auto&& x) { return true; }); } ////////////////////////////////////////////////////////////////////////// // `decltype(tuple_t)` should inherit `_tuple_t` ////////////////////////////////////////////////////////////////////////// { static_assert(std::is_base_of< _tuple_t, decltype(tuple_t) >{}, ""); } ////////////////////////////////////////////////////////////////////////// // Comparable ////////////////////////////////////////////////////////////////////////// { // equal // tuple_t BOOST_HANA_CONSTANT_CHECK(equal(tuple_t<>, tuple_t<>)); BOOST_HANA_CONSTANT_CHECK(not_(equal(tuple_t, tuple_t<>))); BOOST_HANA_CONSTANT_CHECK(not_(equal(tuple_t<>, tuple_t))); BOOST_HANA_CONSTANT_CHECK(equal(tuple_t, tuple_t)); BOOST_HANA_CONSTANT_CHECK(not_(equal(tuple_t, tuple_t))); BOOST_HANA_CONSTANT_CHECK(not_(equal(tuple_t, tuple_t))); BOOST_HANA_CONSTANT_CHECK(equal(tuple_t, tuple_t)); BOOST_HANA_CONSTANT_CHECK(equal(tuple_t, tuple_t)); // tuple_c BOOST_HANA_CONSTANT_CHECK(equal(tuple_c, tuple_c)); BOOST_HANA_CONSTANT_CHECK(not_(equal(tuple_c, tuple_c))); BOOST_HANA_CONSTANT_CHECK(equal(tuple_c, tuple_c)); BOOST_HANA_CONSTANT_CHECK(not_(equal(tuple_c, tuple_c))); BOOST_HANA_CONSTANT_CHECK(equal(tuple_c, tuple_c)); BOOST_HANA_CONSTANT_CHECK(equal(tuple_c, tuple_c)); test::TestComparable{eq_tuples}; } #elif BOOST_HANA_TEST_PART == 2 ////////////////////////////////////////////////////////////////////////// // Orderable ////////////////////////////////////////////////////////////////////////// { test::TestOrderable{ord_tuples}; } #elif BOOST_HANA_TEST_PART == 3 ////////////////////////////////////////////////////////////////////////// // Foldable ////////////////////////////////////////////////////////////////////////// { // unpack { test::_injection<0> f{}; // tuple BOOST_HANA_CONSTANT_CHECK(equal( unpack(make(), f), f() )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(make(eq<0>{}), f), f(eq<0>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(make(eq<0>{}, eq<1>{}), f), f(eq<0>{}, eq<1>{}) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(make(eq<0>{}, eq<1>{}, eq<2>{}), f), f(eq<0>{}, eq<1>{}, eq<2>{}) )); // tuple_t BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t<>, f), f() )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, f), f(type) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, f), f(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, f), f(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, f), f(type, type, type, type) )); // tuple_t with metafunction auto g = metafunction; BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t<>, g), g() )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, g), g(type) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, g), g(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, g), g(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( unpack(tuple_t, g), g(type, type, type, type) )); } // fold.left with tuple_t and initial state { auto f = metafunction; auto s = type; BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t<>, s, f), s )); BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, s, f), f(s, type) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, s, f), f(f(s, type), type) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, s, f), f(f(f(s, type), type), type) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, s, f), f(f(f(f(s, type), type), type), type) )); } // fold.left with tuple_t and no initial state { auto f = metafunction; BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, f), type )); BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, f), f(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, f), f(f(type, type), type) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.left(tuple_t, f), f(f(f(type, type), type), type) )); } // fold.right with tuple_t and an initial state { auto f = metafunction; auto s = type; BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t<>, s, f), s )); BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, s, f), f(type, s) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, s, f), f(type, f(type, s)) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, s, f), f(type, f(type, f(type, s))) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, s, f), f(type, f(type, f(type, f(type, s)))) )); } // fold.right with tuple_t and no initial state { auto f = metafunction; BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, f), type )); BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, f), f(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, f), f(type, f(type, type)) )); BOOST_HANA_CONSTANT_CHECK(equal( fold.right(tuple_t, f), f(type, f(type, f(type, type))) )); } test::TestFoldable{eq_tuples}; } #elif BOOST_HANA_TEST_PART == 4 ////////////////////////////////////////////////////////////////////////// // Iterable ////////////////////////////////////////////////////////////////////////// { // head { // tuple_t BOOST_HANA_CONSTANT_CHECK(equal(head(tuple_t), type)); BOOST_HANA_CONSTANT_CHECK(equal(head(tuple_t), type)); BOOST_HANA_CONSTANT_CHECK(equal(head(tuple_t), type)); // tuple_c BOOST_HANA_CONSTANT_CHECK(equal(head(tuple_c), int_<0>)); BOOST_HANA_CONSTANT_CHECK(equal(head(tuple_c), int_<0>)); BOOST_HANA_CONSTANT_CHECK(equal(head(tuple_c), int_<0>)); } // is_empty { // tuple_t BOOST_HANA_CONSTANT_CHECK(is_empty(tuple_t<>)); BOOST_HANA_CONSTANT_CHECK(not_(is_empty(tuple_t))); BOOST_HANA_CONSTANT_CHECK(not_(is_empty(tuple_t))); // tuple_c BOOST_HANA_CONSTANT_CHECK(is_empty(tuple_c)); BOOST_HANA_CONSTANT_CHECK(not_(is_empty(tuple_c))); BOOST_HANA_CONSTANT_CHECK(not_(is_empty(tuple_c))); BOOST_HANA_CONSTANT_CHECK(not_(is_empty(tuple_c))); } // tail { // tuple_t BOOST_HANA_CONSTANT_CHECK(equal( tail(tuple_t), tuple_t<> )); BOOST_HANA_CONSTANT_CHECK(equal( tail(tuple_t), tuple_t )); BOOST_HANA_CONSTANT_CHECK(equal( tail(tuple_t), tuple_t )); // tuple_c BOOST_HANA_CONSTANT_CHECK(equal( tail(tuple_c), tuple_c )); BOOST_HANA_CONSTANT_CHECK(equal( tail(tuple_c), tuple_c )); BOOST_HANA_CONSTANT_CHECK(equal( tail(tuple_c), tuple_c )); } test::TestIterable{eq_tuples}; } ////////////////////////////////////////////////////////////////////////// // Traversable ////////////////////////////////////////////////////////////////////////// { test::TestTraversable{}; } #elif BOOST_HANA_TEST_PART == 5 ////////////////////////////////////////////////////////////////////////// // Searchable ////////////////////////////////////////////////////////////////////////// { auto eq_tuples = make( make() , make(eq<0>{}) , make(eq<0>{}, eq<1>{}) , make(eq<0>{}, eq<1>{}, eq<2>{}) , make(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}) , make(eq<0>{}, eq<1>{}, eq<2>{}, eq<3>{}, eq<4>{}) ); auto eq_tuple_keys = make(eq<3>{}, eq<5>{}); test::TestSearchable{eq_tuples, eq_tuple_keys}; } #elif BOOST_HANA_TEST_PART == 6 ////////////////////////////////////////////////////////////////////////// // Sequence ////////////////////////////////////////////////////////////////////////// { test::TestSequence{}; } #elif BOOST_HANA_TEST_PART == 7 ////////////////////////////////////////////////////////////////////////// // Functor ////////////////////////////////////////////////////////////////////////// { // transform with tuple_t and a Metafunction { BOOST_HANA_CONSTANT_CHECK(equal( transform(tuple_t<>, metafunction), tuple_t<> )); BOOST_HANA_CONSTANT_CHECK(equal( transform(tuple_t, metafunction), tuple_t::type> )); BOOST_HANA_CONSTANT_CHECK(equal( transform(tuple_t, metafunction), tuple_t::type, F::type> )); BOOST_HANA_CONSTANT_CHECK(equal( transform(tuple_t, metafunction), tuple_t::type, F::type, F::type> )); BOOST_HANA_CONSTANT_CHECK(equal( transform(tuple_t, metafunction), tuple_t::type, F::type, F::type, F::type> )); BOOST_HANA_CONSTANT_CHECK(equal( transform(tuple_t, template_), tuple_t, F, F, F> )); } // fill with tuple_t and a Type { struct z; BOOST_HANA_CONSTANT_CHECK(equal( fill(tuple_t<>, type), tuple_t<> )); BOOST_HANA_CONSTANT_CHECK(equal( fill(tuple_t, type), tuple_t )); BOOST_HANA_CONSTANT_CHECK(equal( fill(tuple_t, type), tuple_t )); BOOST_HANA_CONSTANT_CHECK(equal( fill(tuple_t, type), tuple_t )); } // laws test::TestFunctor{eq_tuples, eq_values}; } ////////////////////////////////////////////////////////////////////////// // Applicative ////////////////////////////////////////////////////////////////////////// { test::TestApplicative{eq_tuples}; } #elif BOOST_HANA_TEST_PART == 8 ////////////////////////////////////////////////////////////////////////// // Monad ////////////////////////////////////////////////////////////////////////// { test::TestMonad{eq_tuples, nested_eqs}; } #elif BOOST_HANA_TEST_PART == 9 ////////////////////////////////////////////////////////////////////////// // MonadPlus ////////////////////////////////////////////////////////////////////////// { // prepend { BOOST_HANA_CONSTANT_CHECK(equal( prepend(long_<0>, tuple_c), tuple_c )); BOOST_HANA_CONSTANT_CHECK(equal( prepend(uint<0>, tuple_c), tuple_c )); BOOST_HANA_CONSTANT_CHECK(equal( prepend(llong<0>, tuple_c), tuple_c )); BOOST_HANA_CONSTANT_CHECK(equal( prepend(ulong<0>, tuple_c), tuple_c )); } // empty { BOOST_HANA_CONSTANT_CHECK(equal( empty(), tuple_c )); BOOST_HANA_CONSTANT_CHECK(equal( empty(), tuple_c )); BOOST_HANA_CONSTANT_CHECK(equal( empty(), tuple_c )); } // laws test::TestMonadPlus{eq_tuples, predicates, eq_values}; } #endif }