From 43b144be2781236ca0d9013182947c80ade421ea Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 27 Dec 2023 23:35:45 +0700 Subject: [PATCH] new deep upcasts, remove is_virtual_base_of --- develop/singles/headers/meta.hpp/meta_all.hpp | 257 +++++------------- .../meta_base/is_virtual_base_of_tests.cpp | 77 ------ .../untests/meta_features/ambiguous_tests.cpp | 21 -- .../untests/meta_issues/random_issue_1.cpp | 6 - headers/meta.hpp/meta_base.hpp | 1 - .../meta.hpp/meta_base/is_virtual_base_of.hpp | 41 --- headers/meta.hpp/meta_base/type_list.hpp | 8 +- .../meta_detail/value_utilities/utraits.hpp | 12 +- headers/meta.hpp/meta_types.hpp | 41 +-- headers/meta.hpp/meta_types/class_type.hpp | 164 ++++------- 10 files changed, 144 insertions(+), 484 deletions(-) delete mode 100644 develop/untests/meta_base/is_virtual_base_of_tests.cpp delete mode 100644 headers/meta.hpp/meta_base/is_virtual_base_of.hpp diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 4b8c188..ecc6ae5 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -1157,38 +1157,6 @@ namespace meta_hpp::detail inline constexpr bool is_in_place_type_v = is_in_place_type::value; } -namespace meta_hpp::detail -{ - namespace impl - { - template < typename From, typename To > - constexpr bool is_virtual_base_of_impl(...) noexcept { - return false; - } - - template < - typename From, - typename To, - decltype(static_cast(std::declval())) = nullptr > - constexpr bool is_virtual_base_of_impl(int) noexcept { - return true; - } - } - - // clang-format off - - template < typename Base, typename Derived > - struct is_virtual_base_of : std::integral_constant && - impl::is_virtual_base_of_impl(0) && - !impl::is_virtual_base_of_impl(0)> {}; - - // clang-format on - - template < typename Base, typename Derived > - inline constexpr bool is_virtual_base_of_v = is_virtual_base_of::value; -} - namespace meta_hpp::detail { class memory_buffer final { @@ -1456,7 +1424,13 @@ namespace meta_hpp::detail namespace meta_hpp::detail { template < typename... Types > - struct type_list {}; + struct type_list { + template < typename F > + // NOLINTNEXTLINE(*-missing-std-forward) + static void for_each(F&& f) { + (f.template operator()(), ...); + } + }; template < std::size_t I > using size_constant = std::integral_constant; @@ -2587,6 +2561,10 @@ namespace meta_hpp return id_type{data_}; } + [[nodiscard]] explicit operator id_type() const noexcept { + return get_id(); + } + [[nodiscard]] type_kind get_kind() const noexcept { return data_->kind; } @@ -2697,10 +2675,6 @@ namespace meta_hpp [[nodiscard]] bool is_direct_base_of() const noexcept; [[nodiscard]] bool is_direct_base_of(const class_type& derived) const noexcept; - template < detail::class_kind Derived > - [[nodiscard]] bool is_virtual_base_of() const noexcept; - [[nodiscard]] bool is_virtual_base_of(const class_type& derived) const noexcept; - template < detail::class_kind Base > [[nodiscard]] bool is_derived_from() const noexcept; [[nodiscard]] bool is_derived_from(const class_type& base) const noexcept; @@ -2709,10 +2683,6 @@ namespace meta_hpp [[nodiscard]] bool is_direct_derived_from() const noexcept; [[nodiscard]] bool is_direct_derived_from(const class_type& base) const noexcept; - template < detail::class_kind Base > - [[nodiscard]] bool is_virtual_derived_from() const noexcept; - [[nodiscard]] bool is_virtual_derived_from(const class_type& base) const noexcept; - [[nodiscard]] function get_function(std::string_view name, bool recursively = true) const noexcept; [[nodiscard]] member get_member(std::string_view name, bool recursively = true) const noexcept; [[nodiscard]] method get_method(std::string_view name, bool recursively = true) const noexcept; @@ -2975,39 +2945,14 @@ namespace meta_hpp::detail struct upcast_func_t final { using upcast_t = void* (*)(void*); + type_id target{}; upcast_t upcast{}; - class_type target{}; - bool is_virtual{}; - - template < typename Derived, typename Base > - requires std::is_base_of_v - upcast_func_t(std::in_place_type_t, std::in_place_type_t); [[nodiscard]] void* apply(void* ptr) const noexcept; [[nodiscard]] const void* apply(const void* ptr) const noexcept; }; - struct upcast_func_list_t final { - using upcasts_t = std::vector; - using vbases_t = std::set>; - - upcasts_t upcasts{}; - vbases_t vbases{}; - bool is_ambiguous{}; - - explicit upcast_func_list_t(const upcast_func_t& in_upcast); - upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases); - - [[nodiscard]] void* apply(void* ptr) const noexcept; - [[nodiscard]] const void* apply(const void* ptr) const noexcept; - - friend upcast_func_list_t operator+(const upcast_func_list_t& l, const upcast_func_list_t& r); - }; - - using base_upcasts_t = std::map>; - using deep_upcasts_t = std::map>; - - base_upcasts_t base_upcasts; + using deep_upcasts_t = std::vector; deep_upcasts_t deep_upcasts; template < class_kind Class > @@ -5762,8 +5707,10 @@ namespace meta_hpp::detail const class_type_data& derived_data = *type_access(derived_class); const class_type_data::deep_upcasts_t& deep_upcasts = derived_data.deep_upcasts; - if ( auto iter{deep_upcasts.find(base)}; iter != deep_upcasts.end() && !iter->second.is_ambiguous ) { - return true; + for ( const auto& upcast : deep_upcasts ) { + if ( upcast.target == base_class ) { + return upcast.upcast != nullptr; + } } } @@ -5785,8 +5732,10 @@ namespace meta_hpp::detail const class_type_data& from_data = *type_access(from); const class_type_data::deep_upcasts_t& deep_upcasts = from_data.deep_upcasts; - if ( auto iter{deep_upcasts.find(to)}; iter != deep_upcasts.end() && !iter->second.is_ambiguous ) { - return iter->second.apply(ptr); + for ( const auto& upcast : deep_upcasts ) { + if ( upcast.target == to ) { + return upcast.upcast != nullptr ? upcast.apply(ptr) : nullptr; + } } return nullptr; @@ -8358,59 +8307,52 @@ namespace meta_hpp::detail , size{class_traits::size} , align{class_traits::align} , argument_types{resolve_types(typename class_traits::argument_types{})} { - if constexpr ( check_base_info_enabled ) { - using meta_base_info = typename Class::meta_base_info; + struct { + class_list base_classes; + deep_upcasts_t deep_upcasts; + } new_base_data; - [this](std::index_sequence) { - struct { - class_list base_classes; - base_upcasts_t base_upcasts; - deep_upcasts_t deep_upcasts; - } new_base_data; + const auto add_new_base = [&new_base_data](auto&& recur) { + const class_type& base_class = resolve_type(); - [[maybe_unused]] const auto add_base_class = [&new_base_data]() { - const class_type& base_class = resolve_type(); - const class_type_data& base_data = *type_access(base_class); - - upcast_func_t self_to_base{std::in_place_type, std::in_place_type}; - upcast_func_list_t self_to_base_list{self_to_base}; - - new_base_data.base_classes.emplace_back(base_class); - new_base_data.base_upcasts.emplace(base_class, self_to_base); - - for ( const auto& [deep_class, base_to_deep] : base_data.deep_upcasts ) { - upcast_func_list_t self_to_deep = self_to_base_list + base_to_deep; - - const auto& [position, emplaced] = new_base_data.deep_upcasts.try_emplace( - deep_class, std::move(self_to_deep) - ); - - if ( !emplaced ) { - position->second.is_ambiguous = is_disjoint(position->second.vbases, self_to_deep.vbases); - } + new_base_data.deep_upcasts.push_back(upcast_func_t{ + .target{base_class}, + .upcast{[]() { + if constexpr ( requires { static_cast(std::declval()); } ) { + return +[](void* from) -> void* { return static_cast(static_cast(from)); }; + } else { + return nullptr; } + }()}, + }); - new_base_data.deep_upcasts.emplace(base_class, std::move(self_to_base_list)); - }; - (add_base_class.template operator()>(), ...); + if constexpr ( std::is_same_v ) { + new_base_data.base_classes.push_back(base_class); + } - base_classes.swap(new_base_data.base_classes); - base_upcasts.swap(new_base_data.base_upcasts); - deep_upcasts.swap(new_base_data.deep_upcasts); - }(std::make_index_sequence>()); - } + recur.template operator()(recur); + }; + + const auto add_new_bases = [&add_new_base](auto&& recur) { + if constexpr ( check_base_info_enabled ) { + using meta_base_info = typename Derived::meta_base_info; + meta_base_info::for_each([&add_new_base, &recur]() { + add_new_base.template operator()(recur); + }); + } else { + (void)recur; + } + }; + + add_new_bases.template operator()(add_new_bases); + + base_classes.swap(new_base_data.base_classes); + deep_upcasts.swap(new_base_data.deep_upcasts); } } namespace meta_hpp::detail { - template < typename Derived, typename Base > - requires std::is_base_of_v - inline class_type_data::upcast_func_t::upcast_func_t(std::in_place_type_t, std::in_place_type_t) - : upcast{[](void* from) -> void* { return static_cast(static_cast(from)); }} - , target{resolve_type()} - , is_virtual{is_virtual_base_of_v} {} - inline void* class_type_data::upcast_func_t::apply(void* ptr) const noexcept { return upcast(ptr); } @@ -8421,52 +8363,6 @@ namespace meta_hpp::detail } } -namespace meta_hpp::detail -{ - inline class_type_data::upcast_func_list_t::upcast_func_list_t(const upcast_func_t& in_upcast) - : upcasts{in_upcast} { - for ( const upcast_func_t& upcast : upcasts ) { - if ( upcast.is_virtual ) { - vbases.emplace(upcast.target); - } - } - } - - inline class_type_data::upcast_func_list_t::upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases) - : upcasts{std::move(in_upcasts)} - , vbases{std::move(in_vbases)} {} - - inline void* class_type_data::upcast_func_list_t::apply(void* ptr) const noexcept { - for ( const upcast_func_t& upcast : upcasts ) { - ptr = upcast.apply(ptr); - } - return ptr; - } - - inline const void* class_type_data::upcast_func_list_t::apply(const void* ptr) const noexcept { - // NOLINTNEXTLINE(*-const-cast) - return apply(const_cast(ptr)); - } - - inline class_type_data::upcast_func_list_t operator+( // - const class_type_data::upcast_func_list_t& l, - const class_type_data::upcast_func_list_t& r - ) { - class_type_data::upcast_func_list_t::upcasts_t new_upcasts; - new_upcasts.reserve(l.upcasts.size() + r.upcasts.size()); - new_upcasts.insert(new_upcasts.end(), l.upcasts.begin(), l.upcasts.end()); - new_upcasts.insert(new_upcasts.end(), r.upcasts.begin(), r.upcasts.end()); - - class_type_data::upcast_func_list_t::vbases_t new_vbases; - new_vbases.insert(l.vbases.begin(), l.vbases.end()); - new_vbases.insert(r.vbases.begin(), r.vbases.end()); - - class_type_data::upcast_func_list_t result{std::move(new_upcasts), std::move(new_vbases)}; - result.is_ambiguous = l.is_ambiguous || r.is_ambiguous; - return result; - } -} - namespace meta_hpp { inline class_bitflags class_type::get_flags() const noexcept { @@ -8576,7 +8472,17 @@ namespace meta_hpp } inline bool class_type::is_base_of(const class_type& derived) const noexcept { - return is_valid() && derived.is_valid() && derived.data_->deep_upcasts.contains(*this); + if ( !is_valid() || !derived.is_valid() ) { + return false; + } + + for ( const auto& upcast : derived.data_->deep_upcasts ) { + if ( upcast.target == *this ) { + return true; + } + } + + return false; } template < detail::class_kind Derived > @@ -8585,24 +8491,14 @@ namespace meta_hpp } inline bool class_type::is_direct_base_of(const class_type& derived) const noexcept { - return is_valid() && derived.is_valid() && derived.data_->base_upcasts.contains(*this); - } - - template < detail::class_kind Derived > - bool class_type::is_virtual_base_of() const noexcept { - return is_virtual_base_of(resolve_type()); - } - - inline bool class_type::is_virtual_base_of(const class_type& derived) const noexcept { if ( !is_valid() || !derived.is_valid() ) { return false; } - using deep_upcasts_t = detail::class_type_data::deep_upcasts_t; - const deep_upcasts_t& deep_upcasts = derived.data_->deep_upcasts; - - if ( auto iter{deep_upcasts.find(*this)}; iter != deep_upcasts.end() ) { - return !iter->second.is_ambiguous && !iter->second.vbases.empty(); + for ( const class_type& base_class : derived.data_->base_classes ) { + if ( base_class == *this ) { + return true; + } } return false; @@ -8626,15 +8522,6 @@ namespace meta_hpp return base.is_direct_base_of(*this); } - template < detail::class_kind Base > - bool class_type::is_virtual_derived_from() const noexcept { - return is_virtual_derived_from(resolve_type()); - } - - inline bool class_type::is_virtual_derived_from(const class_type& base) const noexcept { - return base.is_virtual_base_of(*this); - } - inline function class_type::get_function(std::string_view name, bool recursively) const noexcept { for ( const function& function : data_->functions ) { if ( function.get_name() == name ) { diff --git a/develop/untests/meta_base/is_virtual_base_of_tests.cpp b/develop/untests/meta_base/is_virtual_base_of_tests.cpp deleted file mode 100644 index a9f88b1..0000000 --- a/develop/untests/meta_base/is_virtual_base_of_tests.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/meta.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#include -#include - -namespace -{ - struct A {}; - struct B : virtual A {}; - struct C : virtual A {}; - struct D : B, C {}; - struct E {}; - - struct I {}; - struct J : virtual I {}; - struct K : J {}; -} - -TEST_CASE("meta/meta_base/is_virtual_base_of") { - namespace meta = meta_hpp; - using meta::detail::is_virtual_base_of; - using meta::detail::is_virtual_base_of_v; - - { - static_assert(!is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - - static_assert(is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - - static_assert(!is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - - static_assert(!is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - } - - { - static_assert(!is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - - static_assert(!is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - - static_assert(!is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - static_assert(!is_virtual_base_of_v); - } - - { - static_assert(is_virtual_base_of_v); - - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - static_assert(is_virtual_base_of_v); - } -} diff --git a/develop/untests/meta_features/ambiguous_tests.cpp b/develop/untests/meta_features/ambiguous_tests.cpp index 9cacb4d..824ae8c 100644 --- a/develop/untests/meta_features/ambiguous_tests.cpp +++ b/develop/untests/meta_features/ambiguous_tests.cpp @@ -42,13 +42,6 @@ TEST_CASE("meta/meta_features/ambiguous") { CHECK(meta::is_invocable_with(+[](const A1&){}, B1{})); CHECK(meta::is_invocable_with(+[](const A1&){}, C1{})); CHECK_FALSE(meta::is_invocable_with(+[](const A1&){}, D1{})); - - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); } { @@ -65,13 +58,6 @@ TEST_CASE("meta/meta_features/ambiguous") { CHECK(meta::is_invocable_with(+[](const A2&){}, B2{})); CHECK(meta::is_invocable_with(+[](const A2&){}, C2{})); CHECK(meta::is_invocable_with(+[](const A2&){}, D2{})); - - CHECK(meta::resolve_type().is_virtual_base_of()); - CHECK(meta::resolve_type().is_virtual_base_of()); - CHECK(meta::resolve_type().is_virtual_base_of()); - - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); } { @@ -88,12 +74,5 @@ TEST_CASE("meta/meta_features/ambiguous") { CHECK(meta::is_invocable_with(+[](const A3&){}, B3{})); CHECK(meta::is_invocable_with(+[](const A3&){}, C3{})); CHECK_FALSE(meta::is_invocable_with(+[](const A3&){}, D3{})); - - CHECK(meta::resolve_type().is_virtual_base_of()); - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); } } diff --git a/develop/untests/meta_issues/random_issue_1.cpp b/develop/untests/meta_issues/random_issue_1.cpp index ab2391d..38bca35 100644 --- a/develop/untests/meta_issues/random_issue_1.cpp +++ b/develop/untests/meta_issues/random_issue_1.cpp @@ -51,8 +51,6 @@ TEST_CASE("meta/meta_issues/random/1") { CHECK(meta::try_invoke(+[](const C1&){ return true; }, D1{})); CHECK(meta::try_invoke(+[](const B1&){ return true; }, D1{})); CHECK_FALSE(meta::try_invoke(+[](const A1&){ return true; }, D1{})); - - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); } { @@ -65,8 +63,6 @@ TEST_CASE("meta/meta_issues/random/1") { CHECK(meta::try_invoke(+[](const B2&){ return true; }, E2{})); CHECK(meta::try_invoke(+[](const C2&){ return true; }, E2{})); CHECK(meta::try_invoke(+[](const D2&){ return true; }, E2{})); - - CHECK(meta::resolve_type().is_virtual_base_of()); } { @@ -79,7 +75,5 @@ TEST_CASE("meta/meta_issues/random/1") { CHECK(meta::is_invocable_with(+[](const A3&){ return true; }, B3{})); CHECK(meta::is_invocable_with(+[](const A3&){ return true; }, C3{})); CHECK_FALSE(meta::is_invocable_with(+[](const A3&){ return true; }, D3{})); - - CHECK_FALSE(meta::resolve_type().is_virtual_base_of()); } } diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index 628f5b5..f328378 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -19,7 +19,6 @@ #include "meta_base/intrusive_ptr.hpp" #include "meta_base/is_disjoint.hpp" #include "meta_base/is_in_place_type.hpp" -#include "meta_base/is_virtual_base_of.hpp" #include "meta_base/memory_buffer.hpp" #include "meta_base/noncopyable.hpp" #include "meta_base/nonesuch.hpp" diff --git a/headers/meta.hpp/meta_base/is_virtual_base_of.hpp b/headers/meta.hpp/meta_base/is_virtual_base_of.hpp deleted file mode 100644 index 99b8f44..0000000 --- a/headers/meta.hpp/meta_base/is_virtual_base_of.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/meta.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "base.hpp" - -namespace meta_hpp::detail -{ - namespace impl - { - template < typename From, typename To > - constexpr bool is_virtual_base_of_impl(...) noexcept { - return false; - } - - template < - typename From, - typename To, - decltype(static_cast(std::declval())) = nullptr > - constexpr bool is_virtual_base_of_impl(int) noexcept { - return true; - } - } - - // clang-format off - - template < typename Base, typename Derived > - struct is_virtual_base_of : std::integral_constant && - impl::is_virtual_base_of_impl(0) && - !impl::is_virtual_base_of_impl(0)> {}; - - // clang-format on - - template < typename Base, typename Derived > - inline constexpr bool is_virtual_base_of_v = is_virtual_base_of::value; -} diff --git a/headers/meta.hpp/meta_base/type_list.hpp b/headers/meta.hpp/meta_base/type_list.hpp index fd0e813..1be4ff2 100644 --- a/headers/meta.hpp/meta_base/type_list.hpp +++ b/headers/meta.hpp/meta_base/type_list.hpp @@ -11,7 +11,13 @@ namespace meta_hpp::detail { template < typename... Types > - struct type_list {}; + struct type_list { + template < typename F > + // NOLINTNEXTLINE(*-missing-std-forward) + static void for_each(F&& f) { + (f.template operator()(), ...); + } + }; template < std::size_t I > using size_constant = std::integral_constant; diff --git a/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp b/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp index 8b093d9..fef6626 100644 --- a/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp +++ b/headers/meta.hpp/meta_detail/value_utilities/utraits.hpp @@ -109,8 +109,10 @@ namespace meta_hpp::detail const class_type_data& derived_data = *type_access(derived_class); const class_type_data::deep_upcasts_t& deep_upcasts = derived_data.deep_upcasts; - if ( auto iter{deep_upcasts.find(base)}; iter != deep_upcasts.end() && !iter->second.is_ambiguous ) { - return true; + for ( const auto& upcast : deep_upcasts ) { + if ( upcast.target == base_class ) { + return upcast.upcast != nullptr; + } } } @@ -132,8 +134,10 @@ namespace meta_hpp::detail const class_type_data& from_data = *type_access(from); const class_type_data::deep_upcasts_t& deep_upcasts = from_data.deep_upcasts; - if ( auto iter{deep_upcasts.find(to)}; iter != deep_upcasts.end() && !iter->second.is_ambiguous ) { - return iter->second.apply(ptr); + for ( const auto& upcast : deep_upcasts ) { + if ( upcast.target == to ) { + return upcast.upcast != nullptr ? upcast.apply(ptr) : nullptr; + } } return nullptr; diff --git a/headers/meta.hpp/meta_types.hpp b/headers/meta.hpp/meta_types.hpp index 49523cf..2ca2f45 100644 --- a/headers/meta.hpp/meta_types.hpp +++ b/headers/meta.hpp/meta_types.hpp @@ -126,6 +126,10 @@ namespace meta_hpp return id_type{data_}; } + [[nodiscard]] explicit operator id_type() const noexcept { + return get_id(); + } + [[nodiscard]] type_kind get_kind() const noexcept { return data_->kind; } @@ -236,10 +240,6 @@ namespace meta_hpp [[nodiscard]] bool is_direct_base_of() const noexcept; [[nodiscard]] bool is_direct_base_of(const class_type& derived) const noexcept; - template < detail::class_kind Derived > - [[nodiscard]] bool is_virtual_base_of() const noexcept; - [[nodiscard]] bool is_virtual_base_of(const class_type& derived) const noexcept; - template < detail::class_kind Base > [[nodiscard]] bool is_derived_from() const noexcept; [[nodiscard]] bool is_derived_from(const class_type& base) const noexcept; @@ -248,10 +248,6 @@ namespace meta_hpp [[nodiscard]] bool is_direct_derived_from() const noexcept; [[nodiscard]] bool is_direct_derived_from(const class_type& base) const noexcept; - template < detail::class_kind Base > - [[nodiscard]] bool is_virtual_derived_from() const noexcept; - [[nodiscard]] bool is_virtual_derived_from(const class_type& base) const noexcept; - [[nodiscard]] function get_function(std::string_view name, bool recursively = true) const noexcept; [[nodiscard]] member get_member(std::string_view name, bool recursively = true) const noexcept; [[nodiscard]] method get_method(std::string_view name, bool recursively = true) const noexcept; @@ -514,39 +510,14 @@ namespace meta_hpp::detail struct upcast_func_t final { using upcast_t = void* (*)(void*); + type_id target{}; upcast_t upcast{}; - class_type target{}; - bool is_virtual{}; - - template < typename Derived, typename Base > - requires std::is_base_of_v - upcast_func_t(std::in_place_type_t, std::in_place_type_t); [[nodiscard]] void* apply(void* ptr) const noexcept; [[nodiscard]] const void* apply(const void* ptr) const noexcept; }; - struct upcast_func_list_t final { - using upcasts_t = std::vector; - using vbases_t = std::set>; - - upcasts_t upcasts{}; - vbases_t vbases{}; - bool is_ambiguous{}; - - explicit upcast_func_list_t(const upcast_func_t& in_upcast); - upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases); - - [[nodiscard]] void* apply(void* ptr) const noexcept; - [[nodiscard]] const void* apply(const void* ptr) const noexcept; - - friend upcast_func_list_t operator+(const upcast_func_list_t& l, const upcast_func_list_t& r); - }; - - using base_upcasts_t = std::map>; - using deep_upcasts_t = std::map>; - - base_upcasts_t base_upcasts; + using deep_upcasts_t = std::vector; deep_upcasts_t deep_upcasts; template < class_kind Class > diff --git a/headers/meta.hpp/meta_types/class_type.hpp b/headers/meta.hpp/meta_types/class_type.hpp index e141435..8c6710a 100644 --- a/headers/meta.hpp/meta_types/class_type.hpp +++ b/headers/meta.hpp/meta_types/class_type.hpp @@ -27,59 +27,52 @@ namespace meta_hpp::detail , size{class_traits::size} , align{class_traits::align} , argument_types{resolve_types(typename class_traits::argument_types{})} { - if constexpr ( check_base_info_enabled ) { - using meta_base_info = typename Class::meta_base_info; + struct { + class_list base_classes; + deep_upcasts_t deep_upcasts; + } new_base_data; - [this](std::index_sequence) { - struct { - class_list base_classes; - base_upcasts_t base_upcasts; - deep_upcasts_t deep_upcasts; - } new_base_data; + const auto add_new_base = [&new_base_data](auto&& recur) { + const class_type& base_class = resolve_type(); - [[maybe_unused]] const auto add_base_class = [&new_base_data]() { - const class_type& base_class = resolve_type(); - const class_type_data& base_data = *type_access(base_class); - - upcast_func_t self_to_base{std::in_place_type, std::in_place_type}; - upcast_func_list_t self_to_base_list{self_to_base}; - - new_base_data.base_classes.emplace_back(base_class); - new_base_data.base_upcasts.emplace(base_class, self_to_base); - - for ( const auto& [deep_class, base_to_deep] : base_data.deep_upcasts ) { - upcast_func_list_t self_to_deep = self_to_base_list + base_to_deep; - - const auto& [position, emplaced] = new_base_data.deep_upcasts.try_emplace( - deep_class, std::move(self_to_deep) - ); - - if ( !emplaced ) { - position->second.is_ambiguous = is_disjoint(position->second.vbases, self_to_deep.vbases); - } + new_base_data.deep_upcasts.push_back(upcast_func_t{ + .target{base_class}, + .upcast{[]() { + if constexpr ( requires { static_cast(std::declval()); } ) { + return +[](void* from) -> void* { return static_cast(static_cast(from)); }; + } else { + return nullptr; } + }()}, + }); - new_base_data.deep_upcasts.emplace(base_class, std::move(self_to_base_list)); - }; - (add_base_class.template operator()>(), ...); + if constexpr ( std::is_same_v ) { + new_base_data.base_classes.push_back(base_class); + } - base_classes.swap(new_base_data.base_classes); - base_upcasts.swap(new_base_data.base_upcasts); - deep_upcasts.swap(new_base_data.deep_upcasts); - }(std::make_index_sequence>()); - } + recur.template operator()(recur); + }; + + const auto add_new_bases = [&add_new_base](auto&& recur) { + if constexpr ( check_base_info_enabled ) { + using meta_base_info = typename Derived::meta_base_info; + meta_base_info::for_each([&add_new_base, &recur]() { + add_new_base.template operator()(recur); + }); + } else { + (void)recur; + } + }; + + add_new_bases.template operator()(add_new_bases); + + base_classes.swap(new_base_data.base_classes); + deep_upcasts.swap(new_base_data.deep_upcasts); } } namespace meta_hpp::detail { - template < typename Derived, typename Base > - requires std::is_base_of_v - inline class_type_data::upcast_func_t::upcast_func_t(std::in_place_type_t, std::in_place_type_t) - : upcast{[](void* from) -> void* { return static_cast(static_cast(from)); }} - , target{resolve_type()} - , is_virtual{is_virtual_base_of_v} {} - inline void* class_type_data::upcast_func_t::apply(void* ptr) const noexcept { return upcast(ptr); } @@ -90,52 +83,6 @@ namespace meta_hpp::detail } } -namespace meta_hpp::detail -{ - inline class_type_data::upcast_func_list_t::upcast_func_list_t(const upcast_func_t& in_upcast) - : upcasts{in_upcast} { - for ( const upcast_func_t& upcast : upcasts ) { - if ( upcast.is_virtual ) { - vbases.emplace(upcast.target); - } - } - } - - inline class_type_data::upcast_func_list_t::upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases) - : upcasts{std::move(in_upcasts)} - , vbases{std::move(in_vbases)} {} - - inline void* class_type_data::upcast_func_list_t::apply(void* ptr) const noexcept { - for ( const upcast_func_t& upcast : upcasts ) { - ptr = upcast.apply(ptr); - } - return ptr; - } - - inline const void* class_type_data::upcast_func_list_t::apply(const void* ptr) const noexcept { - // NOLINTNEXTLINE(*-const-cast) - return apply(const_cast(ptr)); - } - - inline class_type_data::upcast_func_list_t operator+( // - const class_type_data::upcast_func_list_t& l, - const class_type_data::upcast_func_list_t& r - ) { - class_type_data::upcast_func_list_t::upcasts_t new_upcasts; - new_upcasts.reserve(l.upcasts.size() + r.upcasts.size()); - new_upcasts.insert(new_upcasts.end(), l.upcasts.begin(), l.upcasts.end()); - new_upcasts.insert(new_upcasts.end(), r.upcasts.begin(), r.upcasts.end()); - - class_type_data::upcast_func_list_t::vbases_t new_vbases; - new_vbases.insert(l.vbases.begin(), l.vbases.end()); - new_vbases.insert(r.vbases.begin(), r.vbases.end()); - - class_type_data::upcast_func_list_t result{std::move(new_upcasts), std::move(new_vbases)}; - result.is_ambiguous = l.is_ambiguous || r.is_ambiguous; - return result; - } -} - namespace meta_hpp { inline class_bitflags class_type::get_flags() const noexcept { @@ -245,7 +192,17 @@ namespace meta_hpp } inline bool class_type::is_base_of(const class_type& derived) const noexcept { - return is_valid() && derived.is_valid() && derived.data_->deep_upcasts.contains(*this); + if ( !is_valid() || !derived.is_valid() ) { + return false; + } + + for ( const auto& upcast : derived.data_->deep_upcasts ) { + if ( upcast.target == *this ) { + return true; + } + } + + return false; } template < detail::class_kind Derived > @@ -254,24 +211,14 @@ namespace meta_hpp } inline bool class_type::is_direct_base_of(const class_type& derived) const noexcept { - return is_valid() && derived.is_valid() && derived.data_->base_upcasts.contains(*this); - } - - template < detail::class_kind Derived > - bool class_type::is_virtual_base_of() const noexcept { - return is_virtual_base_of(resolve_type()); - } - - inline bool class_type::is_virtual_base_of(const class_type& derived) const noexcept { if ( !is_valid() || !derived.is_valid() ) { return false; } - using deep_upcasts_t = detail::class_type_data::deep_upcasts_t; - const deep_upcasts_t& deep_upcasts = derived.data_->deep_upcasts; - - if ( auto iter{deep_upcasts.find(*this)}; iter != deep_upcasts.end() ) { - return !iter->second.is_ambiguous && !iter->second.vbases.empty(); + for ( const class_type& base_class : derived.data_->base_classes ) { + if ( base_class == *this ) { + return true; + } } return false; @@ -295,15 +242,6 @@ namespace meta_hpp return base.is_direct_base_of(*this); } - template < detail::class_kind Base > - bool class_type::is_virtual_derived_from() const noexcept { - return is_virtual_derived_from(resolve_type()); - } - - inline bool class_type::is_virtual_derived_from(const class_type& base) const noexcept { - return base.is_virtual_base_of(*this); - } - inline function class_type::get_function(std::string_view name, bool recursively) const noexcept { for ( const function& function : data_->functions ) { if ( function.get_name() == name ) {