From 1098b61060fa918b52027da3f71acea83608f83e Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Wed, 16 Oct 2024 10:44:40 +0200 Subject: [PATCH] poly: refined inheritance support - close #1184 --- docs/md/poly.md | 7 ++-- src/entt/poly/poly.hpp | 21 +++++----- test/entt/poly/poly.cpp | 90 +++++++++++++++++++++++++++++++++-------- 3 files changed, 87 insertions(+), 31 deletions(-) diff --git a/docs/md/poly.md b/docs/md/poly.md index 1f790150a..644d73827 100644 --- a/docs/md/poly.md +++ b/docs/md/poly.md @@ -230,8 +230,8 @@ For a deduced concept, inheritance is achieved in a few steps: ```cpp struct DrawableAndErasable: entt::type_list<> { template - struct type: typename Drawable::template type { - static constexpr auto base = std::tuple_size_v::type>; + struct type: typename Drawable::type { + static constexpr auto base = Drawable::impl>::size; void erase() { entt::poly_call(*this); } }; @@ -267,8 +267,7 @@ a `decltype` as it follows: ```cpp struct DrawableAndErasable: entt::type_list_cat_t< decltype(as_type_list(std::declval())), - entt::type_list -> { + entt::type_list> { // ... }; ``` diff --git a/src/entt/poly/poly.hpp b/src/entt/poly/poly.hpp index 977148a5c..c8a5b5f98 100644 --- a/src/entt/poly/poly.hpp +++ b/src/entt/poly/poly.hpp @@ -47,20 +47,21 @@ template class poly_vtable { using inspector = typename Concept::template type; - template - static auto vtable_entry(Ret (*)(inspector &, Args...)) -> Ret (*)(basic_any &, Args...); + template + static auto vtable_entry(Ret (*)(Clazz &, Args...)) + -> std::enable_if_t, inspector>, Ret (*)(constness_as_t, Clazz> &, Args...)>; template - static auto vtable_entry(Ret (*)(const inspector &, Args...)) -> Ret (*)(const basic_any &, Args...); + static auto vtable_entry(Ret (*)(Args...)) + -> Ret (*)(const basic_any &, Args...); - template - static auto vtable_entry(Ret (*)(Args...)) -> Ret (*)(const basic_any &, Args...); + template + static auto vtable_entry(Ret (Clazz::*)(Args...)) + -> std::enable_if_t, Ret (*)(basic_any &, Args...)>; - template - static auto vtable_entry(Ret (inspector::*)(Args...)) -> Ret (*)(basic_any &, Args...); - - template - static auto vtable_entry(Ret (inspector::*)(Args...) const) -> Ret (*)(const basic_any &, Args...); + template + static auto vtable_entry(Ret (Clazz::*)(Args...) const) + -> std::enable_if_t, Ret (*)(const basic_any &, Args...)>; template static auto make_vtable(value_list) noexcept diff --git a/test/entt/poly/poly.cpp b/test/entt/poly/poly.cpp index 69b633a01..6ef48cb09 100644 --- a/test/entt/poly/poly.cpp +++ b/test/entt/poly/poly.cpp @@ -55,10 +55,17 @@ struct common_members { namespace { +template +entt::type_list as_type_list(const entt::type_list &); + [[nodiscard]] int absolutely_random() { return 4; } +[[nodiscard]] int three_is_a_magic_number() { + return 3; +} + } // namespace template @@ -127,6 +134,38 @@ struct DefinedEmbedded using impl = entt::value_list<&Type::get>; }; +struct DeducedDerived + : entt::type_list<> { + template + struct type: Deduced::type { + static constexpr auto base = Deduced::impl>::size; + + int three_is_a_magic_number() { + return entt::poly_call(*this); + } + }; + + template + using impl = entt::value_list_cat_t, entt::value_list<&three_is_a_magic_number>>; +}; + +struct DefinedDerived + : entt::type_list_cat_t< + decltype(as_type_list(std::declval())), + entt::type_list> { + template + struct type: Defined::type { + static constexpr auto base = Defined::impl>::size; + + int three_is_a_magic_number() { + return entt::poly_call(*this); + } + }; + + template + using impl = entt::value_list_cat_t, entt::value_list<&three_is_a_magic_number>>; +}; + struct impl { impl() = default; @@ -173,6 +212,15 @@ using PolyEmbeddedTypes = ::testing::Types; TYPED_TEST_SUITE(PolyEmbedded, PolyEmbeddedTypes, ); +template +struct PolyDerived: testing::Test { + using type = entt::basic_poly; +}; + +using PolyDerivedTypes = ::testing::Types; + +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()); } -TYPED_TEST(PolyEmbedded, EmbeddedVtable) { - using poly_type = typename TestFixture::type; - - poly_type poly{impl{}}; - auto *ptr = static_cast(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(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()); +}