/* @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 using namespace boost::hana; struct x1; struct x2; struct x3; struct y1 { }; struct y2 { }; struct y3 { }; template constexpr auto valid_call(F f, T ...t) -> decltype(((void)f(t...)), true) { return true; } constexpr auto valid_call(...) { return false; } // metafunction namespace tc1 { template struct f { struct type; }; using F = decltype(metafunction); BOOST_HANA_CONSTANT_CHECK(metafunction() == type::type>); BOOST_HANA_CONSTANT_CHECK(metafunction(type) == type::type>); BOOST_HANA_CONSTANT_CHECK(metafunction(type, type) == type::type>); BOOST_HANA_CONSTANT_CHECK(metafunction(type, type, type) == type::type>); static_assert(std::is_same, f<>>::value, ""); static_assert(std::is_same, f>::value, ""); static_assert(std::is_same, f>::value, ""); static_assert(std::is_same, f>::value, ""); // Make sure we're SFINAE-friendly template struct no_type { }; static_assert(!valid_call(metafunction), ""); static_assert(!valid_call(metafunction, type), ""); // Make sure we don't read from a non-constexpr variable auto t = type; constexpr auto r = metafunction(t); // `metafunction` with non-Type arguments // 1 arg BOOST_HANA_CONSTANT_CHECK(equal( metafunction(y1{}), metafunction(type) )); // 2 args BOOST_HANA_CONSTANT_CHECK(equal( metafunction(type, y2{}), metafunction(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction(y1{}, type), metafunction(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction(y1{}, y2{}), metafunction(type, type) )); // 3 args BOOST_HANA_CONSTANT_CHECK(equal( metafunction(type, type, y3{}), metafunction(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction(type, y2{}, type), metafunction(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction(type, y2{}, y3{}), metafunction(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction(y1{}, type, type), metafunction(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction(y1{}, type, y3{}), metafunction(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction(y1{}, y2{}, y3{}), metafunction(type, type, type) )); } // metafunction_class namespace tc2 { struct f { template struct apply { struct type; }; }; using F = decltype(metafunction_class); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(), type::type> )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(type), type::type> )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(type, type), type::type> )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(type, type, type), type::type> )); static_assert(std::is_same, f::apply<>>{}, ""); static_assert(std::is_same, f::apply>{}, ""); static_assert(std::is_same, f::apply>{}, ""); static_assert(std::is_same, f::apply>{}, ""); // Make sure we're SFINAE-friendly struct no_type { template struct apply { }; }; static_assert(!valid_call(metafunction_class), ""); static_assert(!valid_call(metafunction_class, type), ""); // Make sure we don't read from a non-constexpr variable auto t = type; constexpr auto r = metafunction_class(t); // `metafunction_class` with non-Type arguments // 1 arg BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(y1{}), metafunction_class(type) )); // 2 args BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(type, y2{}), metafunction_class(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(y1{}, type), metafunction_class(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(y1{}, y2{}), metafunction_class(type, type) )); // 3 args BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(type, type, y3{}), metafunction_class(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(type, y2{}, type), metafunction_class(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(type, y2{}, y3{}), metafunction_class(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(y1{}, type, type), metafunction_class(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(y1{}, type, y3{}), metafunction_class(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( metafunction_class(y1{}, y2{}, y3{}), metafunction_class(type, type, type) )); } // template_ namespace tc3 { template struct f; using F = decltype(template_); BOOST_HANA_CONSTANT_CHECK(equal( template_(), type> )); BOOST_HANA_CONSTANT_CHECK(equal( template_(type), type> )); BOOST_HANA_CONSTANT_CHECK(equal( template_(type, type), type> )); BOOST_HANA_CONSTANT_CHECK(equal( template_(type, type, type), type> )); static_assert(std::is_same::type, f<>>{}, ""); static_assert(std::is_same::type, f>{}, ""); static_assert(std::is_same::type, f>{}, ""); static_assert(std::is_same::type, f>{}, ""); // `template_` with non-Type arguments // 1 arg BOOST_HANA_CONSTANT_CHECK(equal( template_(y1{}), template_(type) )); // 2 args BOOST_HANA_CONSTANT_CHECK(equal( template_(type, y2{}), template_(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( template_(y1{}, type), template_(type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( template_(y1{}, y2{}), template_(type, type) )); // 3 args BOOST_HANA_CONSTANT_CHECK(equal( template_(type, type, y3{}), template_(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( template_(type, y2{}, type), template_(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( template_(type, y2{}, y3{}), template_(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( template_(y1{}, type, type), template_(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( template_(y1{}, type, y3{}), template_(type, type, type) )); BOOST_HANA_CONSTANT_CHECK(equal( template_(y1{}, y2{}, y3{}), template_(type, type, type) )); // Make sure we can use aliases template using alias = T; static_assert(template_(type) == type, ""); // Make sure we don't read from a non-constexpr variable auto t = type; constexpr auto r = template_(t); } // integral namespace tc4 { template struct mf { struct type { }; }; struct mfc { template struct apply { struct type { }; }; }; template struct tpl { }; // make sure `integral(f)(...)` returns the right type static_assert(std::is_same< decltype(integral(metafunction)()), mf<>::type >{}, ""); static_assert(std::is_same< decltype(integral(metafunction)(type)), mf::type >{}, ""); static_assert(std::is_same< decltype(integral(metafunction)(type, type)), mf::type >{}, ""); static_assert(std::is_same< decltype(integral(template_)()), tpl<> >{}, ""); static_assert(std::is_same< decltype(integral(template_)(type)), tpl >{}, ""); static_assert(std::is_same< decltype(integral(template_)(type, type)), tpl >{}, ""); static_assert(std::is_same< decltype(integral(metafunction_class)()), mfc::apply<>::type >{}, ""); static_assert(std::is_same< decltype(integral(metafunction_class)(type)), mfc::apply::type >{}, ""); static_assert(std::is_same< decltype(integral(metafunction_class)(type, type)), mfc::apply::type >{}, ""); // make sure we can perform the call; we already made sure the return type was correct constexpr auto a = integral(metafunction)(); constexpr auto b = integral(metafunction)(type); constexpr auto c = integral(metafunction)(type, type); constexpr auto d = integral(metafunction)(type, type, type); // Make sure we don't read from a non-constexpr variable auto t = type; constexpr auto r = integral(metafunction)(t); } int main() { }