2
0
mirror of https://github.com/boostorg/hana.git synced 2026-01-23 05:32:13 +00:00
Files
hana/test/core/method.cpp
2015-02-01 10:35:17 -05:00

347 lines
11 KiB
C++

/*
@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 <boost/hana/core/datatype.hpp>
#include <boost/hana/core/method.hpp>
#include <boost/hana/core/when.hpp>
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 <typename T, typename _>
struct a_impl<T, when<is_implemented<b_impl<T>, _>>, _> {
static constexpr bool a_from_b = true;
};
template <typename T, typename _>
struct b_impl<T, when<is_implemented<a_impl<T>, _>>, _> {
static constexpr bool b_from_a = true;
};
template <typename T, typename _>
struct b_impl<T, when<is_implemented<c_impl<T>, _>>, _> {
static constexpr bool b_from_c = true;
};
struct MyType;
template <>
struct c_impl<MyType> {
static constexpr bool c_MyType = true;
};
static_assert(dispatch<a_impl<MyType>>::a_from_b, "");
static_assert(dispatch<b_impl<MyType>>::b_from_c, "");
static_assert(dispatch<c_impl<MyType>>::c_MyType, "");
static_assert(is_implemented<a_impl<MyType>>, "");
static_assert(is_implemented<b_impl<MyType>>, "");
static_assert(is_implemented<c_impl<MyType>>, "");
}
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 <typename T, typename U, typename _>
struct a_impl<T, U, when<is_implemented<b_impl<T, U>, _>>, _> {
static constexpr bool a_from_b = true;
};
template <typename T, typename U, typename _>
struct b_impl<T, U, when<is_implemented<a_impl<T, U>, _>>, _> {
static constexpr bool b_from_a = true;
};
template <typename T, typename U, typename _>
struct b_impl<T, U, when<is_implemented<c_impl<T, U>, _>>, _> {
static constexpr bool b_from_c = true;
};
struct MyType;
template <>
struct c_impl<MyType, MyType> {
static constexpr bool c_MyType = true;
};
static_assert(dispatch<a_impl<MyType, MyType>>::a_from_b, "");
static_assert(dispatch<b_impl<MyType, MyType>>::b_from_c, "");
static_assert(dispatch<c_impl<MyType, MyType>>::c_MyType, "");
static_assert(is_implemented<a_impl<MyType, MyType>>, "");
static_assert(is_implemented<b_impl<MyType, MyType>>, "");
static_assert(is_implemented<c_impl<MyType, MyType>>, "");
}
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 <typename T, typename _>
struct a_impl<T, when<is_implemented<a_impl<T>, _>>, _> {
static constexpr bool a_from_a = true;
};
template <typename T, typename _>
struct a_impl<T, when<is_implemented<b_impl<T>, _>>, _> {
static constexpr bool a_from_b = true;
};
struct MyType;
template <>
struct b_impl<MyType> {
static constexpr bool b_MyType = true;
};
static_assert(dispatch<a_impl<MyType>>::a_from_b, "");
static_assert(dispatch<b_impl<MyType>>::b_MyType, "");
static_assert(is_implemented<a_impl<MyType>>, "");
static_assert(is_implemented<b_impl<MyType>>, "");
}
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 <typename T, typename U, typename _>
struct a_impl<T, U, when<is_implemented<a_impl<T, U>, _>>, _> {
static constexpr bool a_from_a = true;
};
template <typename T, typename U, typename _>
struct a_impl<T, U, when<is_implemented<b_impl<T, U>, _>>, _> {
static constexpr bool a_from_b = true;
};
struct MyType;
template <>
struct b_impl<MyType, MyType> {
static constexpr bool b_MyType = true;
};
static_assert(dispatch<a_impl<MyType, MyType>>::a_from_b, "");
static_assert(dispatch<b_impl<MyType, MyType>>::b_MyType, "");
static_assert(is_implemented<a_impl<MyType, MyType>>, "");
static_assert(is_implemented<b_impl<MyType, MyType>>, "");
}
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 <typename T>
struct a_impl<T, when<true>> { };
template <typename T, typename _>
struct a_impl<T, when<true>, _> { };
struct MyType;
template <>
struct a_impl<MyType> {
static constexpr bool a_MyType = true;
};
template <typename T>
struct MyParametricType;
template <typename T>
struct a_impl<MyParametricType<T>> {
static constexpr bool a_MyParametricType = true;
};
static_assert(dispatch<a_impl<MyType>>::a_MyType, "");
static_assert(is_implemented<a_impl<MyType>>, "");
static_assert(dispatch<a_impl<MyParametricType<void>>>::a_MyParametricType, "");
static_assert(is_implemented<a_impl<MyParametricType<void>>>, "");
}
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 <typename T, typename _>
struct a_impl<T, when<true>, _> { };
struct MyType;
template <>
struct a_impl<MyType, when<true>> {
static constexpr bool a_MyType = true;
};
template <typename T>
struct MyParametricType;
template <typename T>
struct a_impl<MyParametricType<T>, when<true>> {
static constexpr bool a_MyParametricType = true;
};
static_assert(dispatch<a_impl<MyType>>::a_MyType, "");
static_assert(is_implemented<a_impl<MyType>>, "");
static_assert(dispatch<a_impl<MyParametricType<void>>>::a_MyParametricType, "");
static_assert(is_implemented<a_impl<MyParametricType<void>>>, "");
}
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 <typename T, typename _>
struct a_impl<T, when<is_implemented<b_impl<T>, _>>, _> {
static constexpr bool a_from_b = true;
};
template <typename T, typename _>
struct b_impl<T, when<is_implemented<a_impl<T>, _>>, _> {
static constexpr bool b_from_a = true;
};
struct MyType1;
template <>
struct a_impl<MyType1> {
static constexpr bool a_MyType1 = true;
};
struct MyType2;
template <>
struct b_impl<MyType2> {
static constexpr bool b_MyType2 = true;
};
static_assert(dispatch<a_impl<MyType1>>::a_MyType1, "");
static_assert(dispatch<b_impl<MyType1>>::b_from_a, "");
static_assert(dispatch<a_impl<MyType2>>::a_from_b, "");
static_assert(dispatch<b_impl<MyType2>>::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 <typename T, typename _>
struct transform_impl<T, when<is_implemented<adjust_impl<T>, _>>, _> {
static constexpr bool transform_from_adjust = true;
};
template <typename T, typename _>
struct adjust_impl<T, when<is_implemented<transform_impl<T>, _>>, _> {
static constexpr bool adjust_from_transform = true;
};
template <typename T, typename _>
struct transform_impl<T, when<
is_implemented<lift_impl<T>, _> && is_implemented<ap_impl<T>, _>
>, _> {
static constexpr bool transform_from_lift_and_ap = true;
};
struct MyType1;
template <>
struct transform_impl<MyType1> {
static constexpr bool transform_MyType1 = true;
};
struct MyType2;
template <>
struct adjust_impl<MyType2> {
static constexpr bool adjust_MyType2 = true;
};
struct MyType3;
template <>
struct lift_impl<MyType3> {
static constexpr bool lift_MyType3 = true;
};
template <>
struct ap_impl<MyType3> {
static constexpr bool ap_MyType3 = true;
};
static_assert(dispatch<transform_impl<MyType1>>::transform_MyType1, "");
static_assert(dispatch<adjust_impl<MyType1>>::adjust_from_transform, "");
static_assert(!is_implemented<lift_impl<MyType1>>, "");
static_assert(!is_implemented<ap_impl<MyType1>>, "");
static_assert(dispatch<transform_impl<MyType2>>::transform_from_adjust, "");
static_assert(dispatch<adjust_impl<MyType2>>::adjust_MyType2, "");
static_assert(!is_implemented<lift_impl<MyType2>>, "");
static_assert(!is_implemented<ap_impl<MyType2>>, "");
static_assert(dispatch<transform_impl<MyType3>>::transform_from_lift_and_ap, "");
static_assert(dispatch<adjust_impl<MyType3>>::adjust_from_transform, "");
static_assert(dispatch<lift_impl<MyType3>>::lift_MyType3, "");
static_assert(dispatch<ap_impl<MyType3>>::ap_MyType3, "");
}
int main() { }