/* @copyright Louis Dionne 2014 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; namespace base_case { // Base case: // a(T) implemented by b(T) // b(T) implemented by a(T) or by c(T) // c(mytype) implemented // ------ // a(mytype) should use c(mytype) instead of recursing BOOST_HANA_METHOD(a_impl); BOOST_HANA_METHOD(b_impl); BOOST_HANA_METHOD(c_impl); template struct a_impl, _>>, _> { static constexpr bool a_from_b = true; }; template struct b_impl, _>>, _> { static constexpr bool b_from_a = true; }; template struct b_impl, _>>, _> { static constexpr bool b_from_c = true; }; struct MyType; template <> struct c_impl { static constexpr bool c_MyType = true; }; static_assert(dispatch>::a_from_b, ""); static_assert(dispatch>::b_from_c, ""); static_assert(dispatch>::c_MyType, ""); static_assert(is_implemented>, ""); static_assert(is_implemented>, ""); static_assert(is_implemented>, ""); } namespace base_case_binary { // Base case with binary methods: // a(T, U) implemented by b(T, U) // b(T, U) implemented by a(T, U) or by c(T, U) // c(mytype, mytype) implemented // ------ // a(mytype, mytype) should use c(mytype, mytype) instead of recursing BOOST_HANA_BINARY_METHOD(a_impl); BOOST_HANA_BINARY_METHOD(b_impl); BOOST_HANA_BINARY_METHOD(c_impl); template struct a_impl, _>>, _> { static constexpr bool a_from_b = true; }; template struct b_impl, _>>, _> { static constexpr bool b_from_a = true; }; template struct b_impl, _>>, _> { static constexpr bool b_from_c = true; }; struct MyType; template <> struct c_impl { static constexpr bool c_MyType = true; }; static_assert(dispatch>::a_from_b, ""); static_assert(dispatch>::b_from_c, ""); static_assert(dispatch>::c_MyType, ""); static_assert(is_implemented>, ""); static_assert(is_implemented>, ""); static_assert(is_implemented>, ""); } namespace degenerate_base_case { // Degenerate version of the base case: // a(T) implemented by a(T) or b(T) // b(mytype) implemented // ------ // a(mytype) should use b(mytype) instead of recursing BOOST_HANA_METHOD(a_impl); BOOST_HANA_METHOD(b_impl); template struct a_impl, _>>, _> { static constexpr bool a_from_a = true; }; template struct a_impl, _>>, _> { static constexpr bool a_from_b = true; }; struct MyType; template <> struct b_impl { static constexpr bool b_MyType = true; }; static_assert(dispatch>::a_from_b, ""); static_assert(dispatch>::b_MyType, ""); static_assert(is_implemented>, ""); static_assert(is_implemented>, ""); } namespace degenerate_base_case_binary { // Degenerate version of the base case with binary methods: // a(T, U) implemented by a(T, U) or b(T, U) // b(mytype, mytype) implemented // ------ // a(mytype, mytype) should use b(mytype, mytype) instead of recursing BOOST_HANA_BINARY_METHOD(a_impl); BOOST_HANA_BINARY_METHOD(b_impl); template struct a_impl, _>>, _> { static constexpr bool a_from_a = true; }; template struct a_impl, _>>, _> { static constexpr bool a_from_b = true; }; struct MyType; template <> struct b_impl { static constexpr bool b_MyType = true; }; static_assert(dispatch>::a_from_b, ""); static_assert(dispatch>::b_MyType, ""); static_assert(is_implemented>, ""); static_assert(is_implemented>, ""); } namespace priority_1 { // Make sure that a method specialized without `when` has priority over a // method specialized with `when` and a method specialized with `when` // and the list of unavailable methods. BOOST_HANA_METHOD(a_impl); template struct a_impl> { }; template struct a_impl, _> { }; struct MyType; template <> struct a_impl { static constexpr bool a_MyType = true; }; template struct MyParametricType; template struct a_impl> { static constexpr bool a_MyParametricType = true; }; static_assert(dispatch>::a_MyType, ""); static_assert(is_implemented>, ""); static_assert(dispatch>>::a_MyParametricType, ""); static_assert(is_implemented>>, ""); } namespace priority_2 { // Make sure that a method specialized with a `when` has priority over a // method specialized with `when` plus the list of unavailable methods. BOOST_HANA_METHOD(a_impl); template struct a_impl, _> { }; struct MyType; template <> struct a_impl> { static constexpr bool a_MyType = true; }; template struct MyParametricType; template struct a_impl, when> { static constexpr bool a_MyParametricType = true; }; static_assert(dispatch>::a_MyType, ""); static_assert(is_implemented>, ""); static_assert(dispatch>>::a_MyParametricType, ""); static_assert(is_implemented>>, ""); } namespace circular_MCD { // Make sure this case works as expected: // a(T) implemented by b(T) // b(T) implemented by a(T) // // a(mytype1) implemented // b(mytype2) implemented // ------ // a(mytype1) and b(mytype1) should use the implemented a(mytype1) // a(mytype2) and b(mytype2) should use the implemented b(mytype2) BOOST_HANA_METHOD(a_impl); BOOST_HANA_METHOD(b_impl); template struct a_impl, _>>, _> { static constexpr bool a_from_b = true; }; template struct b_impl, _>>, _> { static constexpr bool b_from_a = true; }; struct MyType1; template <> struct a_impl { static constexpr bool a_MyType1 = true; }; struct MyType2; template <> struct b_impl { static constexpr bool b_MyType2 = true; }; static_assert(dispatch>::a_MyType1, ""); static_assert(dispatch>::b_from_a, ""); static_assert(dispatch>::a_from_b, ""); static_assert(dispatch>::b_MyType2, ""); } namespace Functor_Applicative_MCD { // Make sure this case works as expected: // transform(T) implemented by adjust(T) // adjust(T) implemented by transform(T) // // transform(T) also implemented by [lift(T) and ap(T)] // // transform(mytype1) implemented // adjust(mytype2) implemented // lift(mytype3) and ap(mytype3) implemented // ------ // transform(mytype1) and adjust(mytype1) should use the implemented transform(mytype1) // lift(mytype1) and ap(mytype1) should not be implemented // // transform(mytype2) and adjust(mytype2) should use the implemented adjust(mytype2) // lift(mytype2) and ap(mytype2) should not be implemented // // transform(mytype3) and adjust(mytype3) should use the implemented lift(mytype3) and ap(mytype3) BOOST_HANA_METHOD(transform_impl); BOOST_HANA_METHOD(adjust_impl); BOOST_HANA_METHOD(lift_impl); BOOST_HANA_METHOD(ap_impl); template struct transform_impl, _>>, _> { static constexpr bool transform_from_adjust = true; }; template struct adjust_impl, _>>, _> { static constexpr bool adjust_from_transform = true; }; template struct transform_impl, _> && is_implemented, _> >, _> { static constexpr bool transform_from_lift_and_ap = true; }; struct MyType1; template <> struct transform_impl { static constexpr bool transform_MyType1 = true; }; struct MyType2; template <> struct adjust_impl { static constexpr bool adjust_MyType2 = true; }; struct MyType3; template <> struct lift_impl { static constexpr bool lift_MyType3 = true; }; template <> struct ap_impl { static constexpr bool ap_MyType3 = true; }; static_assert(dispatch>::transform_MyType1, ""); static_assert(dispatch>::adjust_from_transform, ""); static_assert(!is_implemented>, ""); static_assert(!is_implemented>, ""); static_assert(dispatch>::transform_from_adjust, ""); static_assert(dispatch>::adjust_MyType2, ""); static_assert(!is_implemented>, ""); static_assert(!is_implemented>, ""); static_assert(dispatch>::transform_from_lift_and_ap, ""); static_assert(dispatch>::adjust_from_transform, ""); static_assert(dispatch>::lift_MyType3, ""); static_assert(dispatch>::ap_MyType3, ""); } int main() { }