poly: refined inheritance support - close #1184
This commit is contained in:
@@ -230,8 +230,8 @@ For a deduced concept, inheritance is achieved in a few steps:
|
||||
```cpp
|
||||
struct DrawableAndErasable: entt::type_list<> {
|
||||
template<typename Base>
|
||||
struct type: typename Drawable::template type<Base> {
|
||||
static constexpr auto base = std::tuple_size_v<typename entt::poly_vtable<Drawable>::type>;
|
||||
struct type: typename Drawable::type<Base> {
|
||||
static constexpr auto base = Drawable::impl<Drawable::type<entt::poly_inspector>>::size;
|
||||
void erase() { entt::poly_call<base + 0>(*this); }
|
||||
};
|
||||
|
||||
@@ -267,8 +267,7 @@ a `decltype` as it follows:
|
||||
```cpp
|
||||
struct DrawableAndErasable: entt::type_list_cat_t<
|
||||
decltype(as_type_list(std::declval<Drawable>())),
|
||||
entt::type_list<void()>
|
||||
> {
|
||||
entt::type_list<void()>> {
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
@@ -47,20 +47,21 @@ template<typename Concept, std::size_t Len, std::size_t Align>
|
||||
class poly_vtable {
|
||||
using inspector = typename Concept::template type<poly_inspector>;
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
static auto vtable_entry(Ret (*)(inspector &, Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...);
|
||||
template<typename Ret, typename Clazz, typename... Args>
|
||||
static auto vtable_entry(Ret (*)(Clazz &, Args...))
|
||||
-> std::enable_if_t<std::is_base_of_v<std::remove_const_t<Clazz>, inspector>, Ret (*)(constness_as_t<basic_any<Len, Align>, Clazz> &, Args...)>;
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
static auto vtable_entry(Ret (*)(const inspector &, Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...);
|
||||
static auto vtable_entry(Ret (*)(Args...))
|
||||
-> Ret (*)(const basic_any<Len, Align> &, Args...);
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
static auto vtable_entry(Ret (*)(Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...);
|
||||
template<typename Ret, typename Clazz, typename... Args>
|
||||
static auto vtable_entry(Ret (Clazz::*)(Args...))
|
||||
-> std::enable_if_t<std::is_base_of_v<Clazz, inspector>, Ret (*)(basic_any<Len, Align> &, Args...)>;
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
static auto vtable_entry(Ret (inspector::*)(Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...);
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
static auto vtable_entry(Ret (inspector::*)(Args...) const) -> Ret (*)(const basic_any<Len, Align> &, Args...);
|
||||
template<typename Ret, typename Clazz, typename... Args>
|
||||
static auto vtable_entry(Ret (Clazz::*)(Args...) const)
|
||||
-> std::enable_if_t<std::is_base_of_v<Clazz, inspector>, Ret (*)(const basic_any<Len, Align> &, Args...)>;
|
||||
|
||||
template<auto... Candidate>
|
||||
static auto make_vtable(value_list<Candidate...>) noexcept
|
||||
|
||||
@@ -55,10 +55,17 @@ struct common_members {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename... Type>
|
||||
entt::type_list<Type...> as_type_list(const entt::type_list<Type...> &);
|
||||
|
||||
[[nodiscard]] int absolutely_random() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]] int three_is_a_magic_number() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template<typename Type>
|
||||
@@ -127,6 +134,38 @@ struct DefinedEmbedded
|
||||
using impl = entt::value_list<&Type::get>;
|
||||
};
|
||||
|
||||
struct DeducedDerived
|
||||
: entt::type_list<> {
|
||||
template<typename Base>
|
||||
struct type: Deduced::type<Base> {
|
||||
static constexpr auto base = Deduced::impl<Deduced::type<entt::poly_inspector>>::size;
|
||||
|
||||
int three_is_a_magic_number() {
|
||||
return entt::poly_call<base + 0>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
using impl = entt::value_list_cat_t<typename Deduced::impl<Type>, entt::value_list<&three_is_a_magic_number>>;
|
||||
};
|
||||
|
||||
struct DefinedDerived
|
||||
: entt::type_list_cat_t<
|
||||
decltype(as_type_list(std::declval<Defined>())),
|
||||
entt::type_list<int()>> {
|
||||
template<typename Base>
|
||||
struct type: Defined::type<Base> {
|
||||
static constexpr auto base = Defined::impl<Defined::type<entt::poly_inspector>>::size;
|
||||
|
||||
int three_is_a_magic_number() {
|
||||
return entt::poly_call<base + 0>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
using impl = entt::value_list_cat_t<typename Defined::impl<Type>, entt::value_list<&three_is_a_magic_number>>;
|
||||
};
|
||||
|
||||
struct impl {
|
||||
impl() = default;
|
||||
|
||||
@@ -173,6 +212,15 @@ using PolyEmbeddedTypes = ::testing::Types<DeducedEmbedded, DefinedEmbedded>;
|
||||
|
||||
TYPED_TEST_SUITE(PolyEmbedded, PolyEmbeddedTypes, );
|
||||
|
||||
template<typename Type>
|
||||
struct PolyDerived: testing::Test {
|
||||
using type = entt::basic_poly<Type>;
|
||||
};
|
||||
|
||||
using PolyDerivedTypes = ::testing::Types<DeducedDerived, DefinedDerived>;
|
||||
|
||||
TYPED_TEST_SUITE(PolyDerived, PolyDerivedTypes, );
|
||||
|
||||
TYPED_TEST(Poly, Functionalities) {
|
||||
using poly_type = typename TestFixture::template type<>;
|
||||
|
||||
@@ -196,7 +244,7 @@ TYPED_TEST(Poly, Functionalities) {
|
||||
ASSERT_EQ(alias.data(), &instance);
|
||||
ASSERT_EQ(std::as_const(alias).data(), &instance);
|
||||
|
||||
ASSERT_EQ(value->rand(), 4);
|
||||
ASSERT_EQ(value->rand(), absolutely_random());
|
||||
|
||||
empty = impl{};
|
||||
|
||||
@@ -243,22 +291,6 @@ TYPED_TEST(Poly, Functionalities) {
|
||||
ASSERT_EQ(move.type(), entt::type_id<void>());
|
||||
}
|
||||
|
||||
TYPED_TEST(PolyEmbedded, EmbeddedVtable) {
|
||||
using poly_type = typename TestFixture::type;
|
||||
|
||||
poly_type poly{impl{}};
|
||||
auto *ptr = static_cast<impl *>(poly.data());
|
||||
|
||||
ASSERT_TRUE(poly);
|
||||
ASSERT_NE(poly.data(), nullptr);
|
||||
ASSERT_NE(std::as_const(poly).data(), nullptr);
|
||||
ASSERT_EQ(poly->get(), 0);
|
||||
|
||||
ptr->value = 2;
|
||||
|
||||
ASSERT_EQ(poly->get(), 2);
|
||||
}
|
||||
|
||||
TYPED_TEST(Poly, Owned) {
|
||||
using poly_type = typename TestFixture::template type<>;
|
||||
|
||||
@@ -440,3 +472,27 @@ TYPED_TEST(Poly, NoSboAlignment) {
|
||||
|
||||
ASSERT_EQ(data, nosbo[1].data());
|
||||
}
|
||||
|
||||
TYPED_TEST(PolyEmbedded, EmbeddedVtable) {
|
||||
using poly_type = typename TestFixture::type;
|
||||
|
||||
poly_type poly{impl{}};
|
||||
auto *ptr = static_cast<impl *>(poly.data());
|
||||
|
||||
ASSERT_TRUE(poly);
|
||||
ASSERT_NE(poly.data(), nullptr);
|
||||
ASSERT_NE(std::as_const(poly).data(), nullptr);
|
||||
ASSERT_EQ(poly->get(), 0);
|
||||
|
||||
ptr->value = 2;
|
||||
|
||||
ASSERT_EQ(poly->get(), 2);
|
||||
}
|
||||
|
||||
TYPED_TEST(PolyDerived, InheritanceSupport) {
|
||||
using poly_type = typename TestFixture::type;
|
||||
|
||||
poly_type poly{impl{}};
|
||||
|
||||
ASSERT_EQ(poly->three_is_a_magic_number(), three_is_a_magic_number());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user