From 31482231418dc01cb502deff9d539b1ce3f7bb0d Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 25 Dec 2023 22:56:21 +0700 Subject: [PATCH] new base info wip --- ROADMAP.md | 1 + develop/manuals/meta_manuals/class_manual.cpp | 2 +- .../manuals/meta_manuals/uvalue_manual.cpp | 2 +- develop/singles/headers/meta.hpp/meta_all.hpp | 208 ++++++------------ develop/unbench/cast_function_bench.cpp | 11 +- develop/unbench/dynamic_cast_bench.cpp | 14 +- .../untests/meta_features/ambiguous_tests.cpp | 30 +-- .../untests/meta_features/diamond_tests.cpp | 12 +- .../untests/meta_features/multiple2_tests.cpp | 24 +- .../untests/meta_features/multiple_tests.cpp | 14 +- .../untests/meta_issues/random_issue_1.cpp | 34 +-- develop/untests/meta_states/method_tests.cpp | 10 +- .../untests/meta_types/class_type_tests.cpp | 14 +- develop/untests/meta_utilities/arg2_tests.cpp | 8 +- develop/untests/meta_utilities/arg3_tests.cpp | 8 +- develop/untests/meta_utilities/arg5_tests.cpp | 8 +- develop/untests/meta_utilities/arg7_tests.cpp | 5 - develop/untests/meta_utilities/arg_tests.cpp | 9 +- develop/untests/meta_utilities/cast_tests.cpp | 27 +-- develop/untests/meta_utilities/inst_tests.cpp | 12 +- .../untests/meta_utilities/value3_tests.cpp | 24 +- develop/vendors/CMakeLists.txt | 3 + headers/meta.hpp/meta_binds.hpp | 8 - headers/meta.hpp/meta_binds/class_bind.hpp | 120 ---------- .../{poly_info.hpp => base_info.hpp} | 13 +- headers/meta.hpp/meta_registry.hpp | 2 +- headers/meta.hpp/meta_types.hpp | 6 +- headers/meta.hpp/meta_types/class_type.hpp | 61 ++++- headers/meta.hpp/meta_ucast/ucast.hpp | 2 +- 29 files changed, 206 insertions(+), 486 deletions(-) rename headers/meta.hpp/meta_detail/{poly_info.hpp => base_info.hpp} (78%) diff --git a/ROADMAP.md b/ROADMAP.md index ba576f9..94c1dba 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -9,6 +9,7 @@ - test and support shared libraries - remove `resolve_poly_type`, use `resolve_type(T&&)` instead - add ucast manual +- mark all internal macro with DETAIL prefix ## Thoughts diff --git a/develop/manuals/meta_manuals/class_manual.cpp b/develop/manuals/meta_manuals/class_manual.cpp index ad440b1..b46e605 100644 --- a/develop/manuals/meta_manuals/class_manual.cpp +++ b/develop/manuals/meta_manuals/class_manual.cpp @@ -21,6 +21,7 @@ namespace }; class rectangle : public shape { + META_HPP_ENABLE_BASE_INFO(shape) public: explicit rectangle(int width, int height) : width_{width} @@ -52,7 +53,6 @@ TEST_CASE("meta/meta_manuals/class/type") { // 'rectangle' class type registration meta::class_() - .base_() .constructor_() .method_("get_width", &rectangle::get_width) .method_("get_height", &rectangle::get_height); diff --git a/develop/manuals/meta_manuals/uvalue_manual.cpp b/develop/manuals/meta_manuals/uvalue_manual.cpp index 6546c42..0a6045f 100644 --- a/develop/manuals/meta_manuals/uvalue_manual.cpp +++ b/develop/manuals/meta_manuals/uvalue_manual.cpp @@ -21,6 +21,7 @@ namespace }; class rectangle : public shape { + META_HPP_ENABLE_BASE_INFO(shape) public: explicit rectangle(int width, int height) : width_{width} @@ -52,7 +53,6 @@ TEST_CASE("meta/meta_manuals/uvalue") { // 'rectangle' class type registration meta::class_() - .base_() .constructor_() .method_("get_width", &rectangle::get_width) .method_("get_height", &rectangle::get_height); diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 120be76..9f9e27c 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -2672,7 +2672,6 @@ namespace meta_hpp [[nodiscard]] const any_type_list& get_argument_types() const noexcept; [[nodiscard]] const class_list& get_base_classes() const noexcept; - [[nodiscard]] const class_list& get_derived_classes() const noexcept; [[nodiscard]] const constructor_list& get_constructors() const noexcept; [[nodiscard]] const destructor_list& get_destructors() const noexcept; [[nodiscard]] const function_list& get_functions() const noexcept; @@ -2965,7 +2964,6 @@ namespace meta_hpp::detail // NOLINTEND(*-avoid-const-or-ref-data-members) class_list base_classes; - class_list derived_classes; constructor_list constructors; destructor_list destructors; function_list functions; @@ -2997,8 +2995,8 @@ namespace meta_hpp::detail vbases_t vbases{}; bool is_ambiguous{}; - upcast_func_list_t(const upcast_func_t& _upcast); - upcast_func_list_t(upcasts_t _upcasts, vbases_t _vbases); + 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; @@ -4312,6 +4310,10 @@ namespace meta_hpp::detail class_type type{}; }; + template < typename T > + concept check_base_info_enabled // + = requires { typename T::meta_base_info; }; + template < typename T > concept check_poly_info_enabled // = requires(type_registry& r, const T& v) { @@ -4319,7 +4321,14 @@ namespace meta_hpp::detail }; } -#define META_HPP_ENABLE_POLY_INFO() \ +#define META_HPP_ENABLE_BASE_INFO(...) \ +public: \ + using meta_base_info = ::meta_hpp::detail::type_list<__VA_ARGS__>; \ +\ +private: + +#define META_HPP_ENABLE_POLY_INFO(...) \ + META_HPP_ENABLE_BASE_INFO(__VA_ARGS__) \ public: \ META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \ virtual ::meta_hpp::detail::poly_info get_most_derived_poly_info(::meta_hpp::detail::type_registry& registry) const { \ @@ -4511,11 +4520,6 @@ namespace meta_hpp::detail concept class_bind_destructor_kind // = class_kind && std::is_destructible_v; // - template < typename Base, typename Class > - concept class_bind_base_kind // - = class_kind && class_kind // - && std::derived_from; // - template < typename Member, typename Class > concept class_bind_member_kind // = member_pointer_kind && class_kind // @@ -4596,9 +4600,6 @@ namespace meta_hpp public: explicit class_bind(metadata_map metadata); - template < detail::class_bind_base_kind... Bases > - class_bind& base_(); - template < typename... Args, typename... Opts > requires detail::class_bind_constructor_kind class_bind& constructor_(Opts&&... opts); @@ -5023,83 +5024,6 @@ namespace meta_hpp : type_bind_base{resolve_type(), std::move(metadata)} {} } -namespace meta_hpp::detail::class_bind_impl -{ - using base_upcasts_t = class_type_data::base_upcasts_t; - using deep_upcasts_t = class_type_data::deep_upcasts_t; - - using upcast_func_t = class_type_data::upcast_func_t; - using upcast_func_list_t = class_type_data::upcast_func_list_t; - - using new_bases_db_t = std::vector>; - using deep_upcasts_db_t = std::map>; - using derived_classes_db_t = std::map>; - - template < class_kind Class, class_kind Base > - requires std::is_base_of_v - void update_new_bases_db( // - new_bases_db_t& new_bases_db - ) { - const class_type& new_base = resolve_type(); - - for ( auto&& [db_base, _] : new_bases_db ) { - if ( db_base == new_base ) { - return; - } - } - - new_bases_db.emplace_back( // - new_base, - upcast_func_t{std::in_place_type, std::in_place_type} - ); - } - - inline void update_deep_upcasts_db( // - const class_type& derived_class, - const class_type& new_base_class, - upcast_func_list_t&& derived_to_new_base, - deep_upcasts_db_t& deep_upcasts_db - ) { - const class_type_data& derived_class_data = *type_access(derived_class); - const class_type_data& new_base_class_data = *type_access(new_base_class); - - const auto [deep_upcasts_db_iter, _] = deep_upcasts_db.try_emplace(derived_class, derived_class_data.deep_upcasts); - deep_upcasts_t& derived_deep_upcasts = deep_upcasts_db_iter->second; - - const auto add_derived_deep_upcast = [&derived_deep_upcasts](const class_type& deep_class, upcast_func_list_t&& upcasts) { - auto&& [position, emplaced] = derived_deep_upcasts.try_emplace(deep_class, std::move(upcasts)); - if ( !emplaced ) { - position->second.is_ambiguous = is_disjoint(position->second.vbases, upcasts.vbases); - } - }; - - for ( auto&& [new_deep_class, new_base_to_deep] : new_base_class_data.deep_upcasts ) { - upcast_func_list_t derived_to_new_deep = derived_to_new_base + new_base_to_deep; - add_derived_deep_upcast(new_deep_class, std::move(derived_to_new_deep)); - } - - for ( const class_type& subderived_class : derived_class_data.derived_classes ) { - const class_type_data& subderived_data = *type_access(subderived_class); - upcast_func_t subderived_to_derived = subderived_data.base_upcasts.at(derived_class); - upcast_func_list_t subderived_to_new_base = subderived_to_derived + derived_to_new_base; - update_deep_upcasts_db(subderived_class, new_base_class, std::move(subderived_to_new_base), deep_upcasts_db); - } - - add_derived_deep_upcast(new_base_class, std::move(derived_to_new_base)); - } - - inline void updata_derived_classes_db( // - const class_type& self_class, - const class_type& new_base_class, - derived_classes_db_t& derived_classes_db - ) { - const class_type_data& base_class_data = *type_access(new_base_class); - class_list new_derived_classes{base_class_data.derived_classes}; - insert_or_assign(new_derived_classes, self_class); - derived_classes_db.emplace(new_base_class, std::move(new_derived_classes)); - } -} - namespace meta_hpp { template < detail::class_kind Class > @@ -5110,49 +5034,6 @@ namespace meta_hpp } } - template < detail::class_kind Class > - template < detail::class_bind_base_kind... Bases > - class_bind& class_bind::base_() { - using namespace detail; - using namespace detail::class_bind_impl; - - new_bases_db_t new_bases_db; - (update_new_bases_db(new_bases_db), ...); - - deep_upcasts_db_t deep_upcasts_db; - derived_classes_db_t derived_classes_db; - - class_list new_base_classes{get_data().base_classes}; - base_upcasts_t new_base_upcasts{get_data().base_upcasts}; - - for ( auto&& [new_base_class, self_to_new_base] : new_bases_db ) { - if ( std::find(new_base_classes.begin(), new_base_classes.end(), new_base_class) != new_base_classes.end() ) { - continue; - } - - update_deep_upcasts_db(*this, new_base_class, self_to_new_base, deep_upcasts_db); - updata_derived_classes_db(*this, new_base_class, derived_classes_db); - - new_base_classes.emplace_back(new_base_class); - new_base_upcasts.emplace(new_base_class, self_to_new_base); - } - - get_data().base_classes.swap(new_base_classes); - get_data().base_upcasts.swap(new_base_upcasts); - - for ( auto&& [derived_class, new_deep_upcasts] : deep_upcasts_db ) { - class_type_data& derived_data = *type_access(derived_class); - derived_data.deep_upcasts.swap(new_deep_upcasts); - } - - for ( auto&& [base_class, new_derived_classes] : derived_classes_db ) { - class_type_data& base_data = *type_access(base_class); - base_data.derived_classes.swap(new_derived_classes); - } - - return *this; - } - template < detail::class_kind Class > template < typename... Args, typename... Opts > requires detail::class_bind_constructor_kind @@ -8476,7 +8357,48 @@ namespace meta_hpp::detail , flags{class_traits::make_flags()} , size{class_traits::size} , align{class_traits::align} - , argument_types{resolve_types(typename class_traits::argument_types{})} {} + , argument_types{resolve_types(typename class_traits::argument_types{})} { + if constexpr ( check_base_info_enabled ) { + using meta_base_info = typename Class::meta_base_info; + + [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_class = [&new_base_data](std::in_place_type_t) { + const class_type& base_class = resolve_type(); + const class_type_data& base_class_data = *type_access(base_class); + + upcast_func_t self_to_base{std::in_place_type, std::in_place_type}; + + 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_class_data.deep_upcasts ) { + upcast_func_list_t self_to_deep = self_to_base + 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.emplace(base_class, upcast_func_list_t{self_to_base}); + }; + (add_new_base_class(std::in_place_type>), ...); + + 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>()); + } + } } namespace meta_hpp::detail @@ -8500,8 +8422,8 @@ namespace meta_hpp::detail namespace meta_hpp::detail { - inline class_type_data::upcast_func_list_t::upcast_func_list_t(const upcast_func_t& _upcast) - : upcasts{_upcast} { + 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); @@ -8509,9 +8431,9 @@ namespace meta_hpp::detail } } - inline class_type_data::upcast_func_list_t::upcast_func_list_t(upcasts_t _upcasts, vbases_t _vbases) - : upcasts{std::move(_upcasts)} - , vbases{std::move(_vbases)} {} + 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 ) { @@ -8538,7 +8460,9 @@ namespace meta_hpp::detail new_vbases.insert(l.vbases.begin(), l.vbases.end()); new_vbases.insert(r.vbases.begin(), r.vbases.end()); - return class_type_data::upcast_func_list_t{std::move(new_upcasts), std::move(new_vbases)}; + 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; } } @@ -8572,10 +8496,6 @@ namespace meta_hpp return data_->base_classes; } - inline const class_list& class_type::get_derived_classes() const noexcept { - return data_->derived_classes; - } - inline const constructor_list& class_type::get_constructors() const noexcept { return data_->constructors; } diff --git a/develop/unbench/cast_function_bench.cpp b/develop/unbench/cast_function_bench.cpp index 4c797e4..faccfd5 100644 --- a/develop/unbench/cast_function_bench.cpp +++ b/develop/unbench/cast_function_bench.cpp @@ -28,14 +28,17 @@ namespace struct base2 : base1 { unsigned b2{2}; + META_HPP_ENABLE_BASE_INFO(base1) }; struct base3 : base2 { unsigned b3{3}; + META_HPP_ENABLE_BASE_INFO(base2) }; struct base4 : base3 { unsigned b4{4}; + META_HPP_ENABLE_BASE_INFO(base3) }; unsigned static_function_1(base1* b1) { @@ -67,14 +70,6 @@ namespace static_acc = 0; } - const bool registered = [](){ - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - return true; - }(); - meta::scope meta_bench_scope = meta::local_scope_("") .function_("cast_function_1", &static_function_1) .function_("cast_function_2", &static_function_2) diff --git a/develop/unbench/dynamic_cast_bench.cpp b/develop/unbench/dynamic_cast_bench.cpp index 9d6e4a4..ebd12eb 100644 --- a/develop/unbench/dynamic_cast_bench.cpp +++ b/develop/unbench/dynamic_cast_bench.cpp @@ -28,17 +28,17 @@ namespace struct base2 : base1 { unsigned b2{2}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(base1) }; struct base3 : base2 { unsigned b3{3}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(base2) }; struct base4 : base3 { unsigned b4{4}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(base3) }; base4* dynamic_cast_1(base1* b1) { @@ -56,14 +56,6 @@ namespace base4* dynamic_cast_4(base4* b4) { return dynamic_cast(b4); } - - const bool registered = [](){ - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - return true; - }(); } // diff --git a/develop/untests/meta_features/ambiguous_tests.cpp b/develop/untests/meta_features/ambiguous_tests.cpp index 65267fa..9cacb4d 100644 --- a/develop/untests/meta_features/ambiguous_tests.cpp +++ b/develop/untests/meta_features/ambiguous_tests.cpp @@ -10,29 +10,25 @@ namespace { struct A1 { std::string a1{"a1"}; }; - struct B1 : A1 { std::string b1{"b1"}; }; - struct C1 : A1 { std::string c1{"c1"}; }; - struct D1 : B1, C1 { std::string d1{"d1"}; }; + struct B1 : A1 { std::string b1{"b1"}; META_HPP_ENABLE_BASE_INFO(A1) }; + struct C1 : A1 { std::string c1{"c1"}; META_HPP_ENABLE_BASE_INFO(A1) }; + struct D1 : B1, C1 { std::string d1{"d1"}; META_HPP_ENABLE_BASE_INFO(B1, C1) }; struct A2 { std::string a2{"a2"}; }; - struct B2 : virtual A2 { std::string b2{"b2"}; }; - struct C2 : virtual A2 { std::string c2{"c2"}; }; - struct D2 : B2, C2 { std::string d2{"d2"}; }; + struct B2 : virtual A2 { std::string b2{"b2"}; META_HPP_ENABLE_BASE_INFO(A2) }; + struct C2 : virtual A2 { std::string c2{"c2"}; META_HPP_ENABLE_BASE_INFO(A2) }; + struct D2 : B2, C2 { std::string d2{"d2"}; META_HPP_ENABLE_BASE_INFO(B2, C2) }; struct A3 { std::string a3{"a3"}; }; - struct B3 : virtual A3 { std::string b3{"b3"}; }; - struct C3 : A3 { std::string c3{"c3"}; }; - struct D3 : B3, C3 { std::string d3{"d3"}; }; + struct B3 : virtual A3 { std::string b3{"b3"}; META_HPP_ENABLE_BASE_INFO(A3) }; + struct C3 : A3 { std::string c3{"c3"}; META_HPP_ENABLE_BASE_INFO(A3) }; + struct D3 : B3, C3 { std::string d3{"d3"}; META_HPP_ENABLE_BASE_INFO(B3, C3) }; } TEST_CASE("meta/meta_features/ambiguous") { namespace meta = meta_hpp; { - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - // A1 < B1 // < D1 // A1 < C1 @@ -56,10 +52,6 @@ TEST_CASE("meta/meta_features/ambiguous") { } { - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - // A2 <= B2 // < D2 // A2 <= C2 @@ -83,10 +75,6 @@ TEST_CASE("meta/meta_features/ambiguous") { } { - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - // A3 <= B3 // < D3 // A3 < C3 diff --git a/develop/untests/meta_features/diamond_tests.cpp b/develop/untests/meta_features/diamond_tests.cpp index 9319eef..44e63f1 100644 --- a/develop/untests/meta_features/diamond_tests.cpp +++ b/develop/untests/meta_features/diamond_tests.cpp @@ -22,9 +22,9 @@ namespace META_HPP_ENABLE_POLY_INFO() }; - struct B : virtual A { META_HPP_ENABLE_POLY_INFO() }; - struct C : virtual A { META_HPP_ENABLE_POLY_INFO() }; - struct D : B, C { META_HPP_ENABLE_POLY_INFO() }; + struct B : virtual A { META_HPP_ENABLE_POLY_INFO(A) }; + struct C : virtual A { META_HPP_ENABLE_POLY_INFO(A) }; + struct D : B, C { META_HPP_ENABLE_POLY_INFO(B, C) }; struct E {}; } @@ -35,12 +35,6 @@ TEST_CASE("meta/meta_features/diamond") { using meta::detail::type_registry; type_registry& r{type_registry::instance()}; - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_().base_(); - meta::class_(); - // * <- B <- * // A D // * <- C <- * diff --git a/develop/untests/meta_features/multiple2_tests.cpp b/develop/untests/meta_features/multiple2_tests.cpp index 88cc309..0e51c6f 100644 --- a/develop/untests/meta_features/multiple2_tests.cpp +++ b/develop/untests/meta_features/multiple2_tests.cpp @@ -10,31 +10,21 @@ namespace { struct A { std::string a{"a"}; }; - struct B0 : virtual A { std::string b0{"b0"}; }; - struct B1 : virtual A { std::string b1{"b1"}; }; + struct B0 : virtual A { std::string b0{"b0"}; META_HPP_ENABLE_BASE_INFO(A) }; + struct B1 : virtual A { std::string b1{"b1"}; META_HPP_ENABLE_BASE_INFO(A) }; - struct C : B0, B1 { std::string c{"c"}; }; + struct C : B0, B1 { std::string c{"c"}; META_HPP_ENABLE_BASE_INFO(B0, B1) }; - struct D0 : C { std::string d0{"d0"}; }; - struct E0 : D0 { std::string e0{"e0"}; }; + struct D0 : C { std::string d0{"d0"}; META_HPP_ENABLE_BASE_INFO(C) }; + struct E0 : D0 { std::string e0{"e0"}; META_HPP_ENABLE_BASE_INFO(D0) }; - struct D1 : C { std::string d1{"d1"}; }; - struct E1 : D1 { std::string e1{"e1"}; }; + struct D1 : C { std::string d1{"d1"}; META_HPP_ENABLE_BASE_INFO(C) }; + struct E1 : D1 { std::string e1{"e1"}; META_HPP_ENABLE_BASE_INFO(D1) }; } TEST_CASE("meta/meta_features/multiple2/_") { namespace meta = meta_hpp; - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - - meta::class_().base_(); - meta::class_().base_(); - - meta::class_().base_(); - meta::class_().base_(); - // * <- B0 <- * * <- D0 * <- E0 // A C // * <- B1 <- * * <- D1 * <- E1 diff --git a/develop/untests/meta_features/multiple_tests.cpp b/develop/untests/meta_features/multiple_tests.cpp index 25481f8..8075c57 100644 --- a/develop/untests/meta_features/multiple_tests.cpp +++ b/develop/untests/meta_features/multiple_tests.cpp @@ -21,22 +21,16 @@ namespace virtual ~A() = default; }; - struct B : A {}; - struct C : A {}; - struct D : B, C {}; - struct E : D {}; + struct B : A { META_HPP_ENABLE_BASE_INFO(A) }; + struct C : A { META_HPP_ENABLE_BASE_INFO(A) }; + struct D : B, C { META_HPP_ENABLE_BASE_INFO(B, C) }; + struct E : D { META_HPP_ENABLE_BASE_INFO(D) }; struct F {}; } TEST_CASE("meta/meta_features/multiple/_") { namespace meta = meta_hpp; - meta::class_().base_(); - meta::class_().base_(); - - meta::class_().base_(); - meta::class_().base_(); - // A * <- B <- * // D * <- E // A * <- C <- * diff --git a/develop/untests/meta_issues/random_issue_1.cpp b/develop/untests/meta_issues/random_issue_1.cpp index 39c918e..ab2391d 100644 --- a/develop/untests/meta_issues/random_issue_1.cpp +++ b/develop/untests/meta_issues/random_issue_1.cpp @@ -10,43 +10,38 @@ namespace { struct A1 {}; - struct B1 : A1 {}; - struct C1 : A1 {}; - struct D1 : B1, C1 {}; + struct B1 : A1 { META_HPP_ENABLE_BASE_INFO(A1) }; + struct C1 : A1 { META_HPP_ENABLE_BASE_INFO(A1) }; + struct D1 : B1, C1 { META_HPP_ENABLE_BASE_INFO(B1, C1) }; // A1 <- B1 <- * // D1 // A1 <- C1 <- * struct A2 {}; - struct B2 : virtual A2 {}; - struct C2 : virtual B2 {}; - struct D2 : virtual B2 {}; - struct E2 : C2, D2 {}; + struct B2 : virtual A2 { META_HPP_ENABLE_BASE_INFO(A2) }; + struct C2 : virtual B2 { META_HPP_ENABLE_BASE_INFO(B2) }; + struct D2 : virtual B2 { META_HPP_ENABLE_BASE_INFO(B2) }; + struct E2 : C2, D2 { META_HPP_ENABLE_BASE_INFO(C2, D2) }; // A2 <= B2 <= C2 <- * // E2 // A2 <= B2 <= D2 <- * struct A3 {}; - struct B3 : virtual A3 {}; - struct C3 : A3 {}; - struct D3 : B3, C3 {}; + struct B3 : virtual A3 { META_HPP_ENABLE_BASE_INFO(A3) }; + struct C3 : A3 { META_HPP_ENABLE_BASE_INFO(A3) }; + struct D3 : B3, C3 { META_HPP_ENABLE_BASE_INFO(B3, C3) }; // A3 <= B3 <- * // D3 // A3 <- C3 <- * - } TEST_CASE("meta/meta_issues/random/1") { namespace meta = meta_hpp; { - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - CHECK(meta::is_invocable_with(+[](const D1&){ return true; }, D1{})); CHECK(meta::is_invocable_with(+[](const C1&){ return true; }, D1{})); CHECK(meta::is_invocable_with(+[](const B1&){ return true; }, D1{})); @@ -61,11 +56,6 @@ TEST_CASE("meta/meta_issues/random/1") { } { - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - CHECK(meta::is_invocable_with(+[](const A2&){ return true; }, E2{})); CHECK(meta::is_invocable_with(+[](const B2&){ return true; }, E2{})); CHECK(meta::is_invocable_with(+[](const C2&){ return true; }, E2{})); @@ -80,10 +70,6 @@ TEST_CASE("meta/meta_issues/random/1") { } { - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_(); - static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); static_assert(std::is_invocable_v); diff --git a/develop/untests/meta_states/method_tests.cpp b/develop/untests/meta_states/method_tests.cpp index 8cd0dab..bbe0a31 100644 --- a/develop/untests/meta_states/method_tests.cpp +++ b/develop/untests/meta_states/method_tests.cpp @@ -53,10 +53,15 @@ namespace // int ii = 0; + + // + + META_HPP_ENABLE_BASE_INFO(base) }; struct derived_clazz : fake, clazz { int pure_virtual_method() override { return -2; } + META_HPP_ENABLE_BASE_INFO(fake, clazz) }; struct clazz2 {}; @@ -69,8 +74,6 @@ TEST_CASE("meta/meta_states/method/_") { .method_("pure_virtual_method", &base::pure_virtual_method); meta::class_() - .base_() - .method_("non_const_method", &clazz::non_const_method) .method_("non_const_method_noexcept", &clazz::non_const_method_noexcept) @@ -88,9 +91,6 @@ TEST_CASE("meta/meta_states/method/_") { .method_("const_method_rref", &clazz::const_method_rref) .method_("const_method_noexcept_rref", &clazz::const_method_noexcept_rref); - - meta::class_() - .base_(); } TEST_CASE("meta/meta_states/method") { diff --git a/develop/untests/meta_types/class_type_tests.cpp b/develop/untests/meta_types/class_type_tests.cpp index 904f1f2..508a5c4 100644 --- a/develop/untests/meta_types/class_type_tests.cpp +++ b/develop/untests/meta_types/class_type_tests.cpp @@ -49,10 +49,12 @@ namespace static double derived_function() { return 3.0; } static constexpr double derived_variable = 3.0; + META_HPP_ENABLE_BASE_INFO(base_clazz_1, base_clazz_2) }; struct final_derived_clazz final : derived_clazz { using derived_clazz::derived_clazz; + META_HPP_ENABLE_BASE_INFO(derived_clazz) }; template < typename... Args > @@ -64,7 +66,6 @@ TEST_CASE("meta/meta_types/class_type/_") { meta::class_() .constructor_() - .base_<>() .member_("base_member_1", &base_clazz_1::base_member_1) .method_("base_method_1", &base_clazz_1::base_method_1) .function_("base_function_1", &base_clazz_1::base_function_1) @@ -83,15 +84,13 @@ TEST_CASE("meta/meta_types/class_type/_") { meta::class_() .constructor_() - .base_() .member_("derived_member", &derived_clazz::derived_member) .method_("derived_method", &derived_clazz::derived_method) .function_("derived_function", &derived_clazz::derived_function) .variable_("derived_variable", &derived_clazz::derived_variable); meta::class_() - .constructor_() - .base_(); + .constructor_(); } TEST_CASE("meta/meta_types/class_type") { @@ -209,13 +208,6 @@ TEST_CASE("meta/meta_types/class_type") { CHECK(final_derived_clazz_type.get_base_classes() == meta::class_list{derived_clazz_type}); } - SUBCASE("get_derived_classes") { - CHECK(base_clazz_1_type.get_derived_classes() == meta::class_list{derived_clazz_type}); - CHECK(base_clazz_2_type.get_derived_classes() == meta::class_list{derived_clazz_type}); - CHECK(derived_clazz_type.get_derived_classes() == meta::class_list{final_derived_clazz_type}); - CHECK(final_derived_clazz_type.get_derived_classes() == meta::class_list{}); - } - SUBCASE("get_functions") { CHECK(base_clazz_1_type.get_functions().size() == 3); CHECK(base_clazz_2_type.get_functions().size() == 1); diff --git a/develop/untests/meta_utilities/arg2_tests.cpp b/develop/untests/meta_utilities/arg2_tests.cpp index ea2b513..9a84b9e 100644 --- a/develop/untests/meta_utilities/arg2_tests.cpp +++ b/develop/untests/meta_utilities/arg2_tests.cpp @@ -32,16 +32,19 @@ namespace struct B : virtual A { int bi = 2; [[nodiscard]] int f() const { return bi; } + META_HPP_ENABLE_BASE_INFO(A) }; struct C : virtual A { int ci = 3; [[nodiscard]] int f() const { return ci; } + META_HPP_ENABLE_BASE_INFO(A) }; struct D : B, C { int di = 4; [[nodiscard]] int f() const { return di; } + META_HPP_ENABLE_BASE_INFO(B, C) }; } @@ -51,11 +54,6 @@ TEST_CASE("meta/meta_utilities/arg2") { // * <- B <- * // A D // * <- C <- * - - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_().base_(); } TEST_CASE("meta/meta_utilities/arg2/cast") { diff --git a/develop/untests/meta_utilities/arg3_tests.cpp b/develop/untests/meta_utilities/arg3_tests.cpp index a96d670..b48ea00 100644 --- a/develop/untests/meta_utilities/arg3_tests.cpp +++ b/develop/untests/meta_utilities/arg3_tests.cpp @@ -25,16 +25,19 @@ namespace struct B : virtual A { int bi = 2; [[nodiscard]] int f() const { return bi; } + META_HPP_ENABLE_BASE_INFO(A) }; struct C : virtual A { int ci = 3; [[nodiscard]] int f() const { return ci; } + META_HPP_ENABLE_BASE_INFO(A) }; struct D : B, C { int di = 4; [[nodiscard]] int f() const { return di; } + META_HPP_ENABLE_BASE_INFO(B, C) }; } @@ -44,11 +47,6 @@ TEST_CASE("meta/meta_utilities/arg3") { // * <- B <- * // A D // * <- C <- * - - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_().base_(); } TEST_CASE("meta/meta_utilities/arg3/cast") { diff --git a/develop/untests/meta_utilities/arg5_tests.cpp b/develop/untests/meta_utilities/arg5_tests.cpp index 00c3d1d..996e2d1 100644 --- a/develop/untests/meta_utilities/arg5_tests.cpp +++ b/develop/untests/meta_utilities/arg5_tests.cpp @@ -23,14 +23,17 @@ namespace struct B : virtual A { int bi = 2; + META_HPP_ENABLE_BASE_INFO(A) }; struct C : virtual A { int ci = 3; + META_HPP_ENABLE_BASE_INFO(A) }; struct D : B, C { int di = 4; + META_HPP_ENABLE_BASE_INFO(B, C) }; } @@ -40,11 +43,6 @@ TEST_CASE("meta/meta_utilities/arg5") { // * <- B <- * // A D // * <- C <- * - - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_().base_(); } TEST_CASE("meta/meta_utilities/arg5/cast") { diff --git a/develop/untests/meta_utilities/arg7_tests.cpp b/develop/untests/meta_utilities/arg7_tests.cpp index 0cc7745..0979254 100644 --- a/develop/untests/meta_utilities/arg7_tests.cpp +++ b/develop/untests/meta_utilities/arg7_tests.cpp @@ -40,11 +40,6 @@ TEST_CASE("meta/meta_utilities/arg7") { // * <- B <- * // A D // * <- C <- * - - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_().base_().base_(); } TEST_CASE("meta/meta_utilities/arg7/cast/to_void") { diff --git a/develop/untests/meta_utilities/arg_tests.cpp b/develop/untests/meta_utilities/arg_tests.cpp index 4549812..894e895 100644 --- a/develop/untests/meta_utilities/arg_tests.cpp +++ b/develop/untests/meta_utilities/arg_tests.cpp @@ -21,6 +21,7 @@ namespace }; struct dclazz : fake, clazz { + META_HPP_ENABLE_BASE_INFO(fake, clazz) }; int f1(int v) { return v; } @@ -110,14 +111,6 @@ namespace }\ } -TEST_CASE("meta/meta_utilities/arg") { - namespace meta = meta_hpp; - - meta::class_(); - meta::class_(); - meta::class_().base_().base_(); -} - TEST_CASE("meta/meta_utilities/arg/refs") { namespace meta = meta_hpp; using meta::detail::uarg; diff --git a/develop/untests/meta_utilities/cast_tests.cpp b/develop/untests/meta_utilities/cast_tests.cpp index c975576..79e2adb 100644 --- a/develop/untests/meta_utilities/cast_tests.cpp +++ b/develop/untests/meta_utilities/cast_tests.cpp @@ -21,14 +21,14 @@ namespace B1() = default; B1(const B1&) = default; char b{'b'}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(A1) }; struct C1 : B1 { C1() = default; C1(const C1&) = default; char c{'c'}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(B1) }; // A1 <- B1 <- C1 @@ -45,14 +45,14 @@ namespace B2() = default; B2(const B2&) = default; char b{'b'}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(A2) }; struct C2 : virtual A2 { C2() = default; C2(const C2&) = default; char c{'c'}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(A2) }; @@ -68,14 +68,14 @@ namespace E2() = default; E2(const E2&) = default; char e{'e'}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(D2) }; struct F2 : B2, C2, E2 { F2() = default; F2(const F2&) = default; char f{'f'}; - META_HPP_ENABLE_POLY_INFO() + META_HPP_ENABLE_POLY_INFO(B2, C2, E2) }; @@ -119,21 +119,6 @@ namespace } } -TEST_CASE("meta/meta_utilities/ucast/_") { - namespace meta = meta_hpp; - - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); - meta::class_(); - meta::class_().base_(); - meta::class_().base_(); -} - TEST_CASE("meta/meta_utilities/ucast") { namespace meta = meta_hpp; diff --git a/develop/untests/meta_utilities/inst_tests.cpp b/develop/untests/meta_utilities/inst_tests.cpp index b19bdba..c7c1bbf 100644 --- a/develop/untests/meta_utilities/inst_tests.cpp +++ b/develop/untests/meta_utilities/inst_tests.cpp @@ -23,7 +23,9 @@ namespace [[nodiscard]] int m6() const && { return ii; } }; - struct dclazz : fake, clazz {}; + struct dclazz : fake, clazz { + META_HPP_ENABLE_BASE_INFO(fake, clazz) + }; } // NOLINTNEXTLINE(*-macro-usage) @@ -70,14 +72,6 @@ namespace }\ } -TEST_CASE("meta/meta_utilities/inst2") { - namespace meta = meta_hpp; - - meta::class_(); - meta::class_(); - meta::class_().base_().base_(); -} - TEST_CASE("meta/meta_utilities/inst2/refs") { namespace meta = meta_hpp; using meta::detail::uarg; diff --git a/develop/untests/meta_utilities/value3_tests.cpp b/develop/untests/meta_utilities/value3_tests.cpp index 009be4b..13482c1 100644 --- a/develop/untests/meta_utilities/value3_tests.cpp +++ b/develop/untests/meta_utilities/value3_tests.cpp @@ -15,41 +15,25 @@ namespace struct base1 : virtual base0 { int j{42}; + META_HPP_ENABLE_BASE_INFO(base0) }; struct base2 : virtual base0 { int k{84}; + META_HPP_ENABLE_BASE_INFO(base0) }; struct derived : base1, base2 { int l{168}; + META_HPP_ENABLE_BASE_INFO(base1, base2) }; struct derived2 : base1, base2 { int m{336}; + META_HPP_ENABLE_BASE_INFO(base1, base2) }; } -TEST_CASE("meta/meta_utilities/value3") { - namespace meta = meta_hpp; - - meta::class_(); - - meta::class_() - .base_(); - - meta::class_() - .base_(); - - meta::class_() - .base_() - .base_(); - - meta::class_() - .base_() - .base_(); -} - TEST_CASE("meta/meta_utilities/value3/get_type") { namespace meta = meta_hpp; diff --git a/develop/vendors/CMakeLists.txt b/develop/vendors/CMakeLists.txt index 8167d76..559408e 100644 --- a/develop/vendors/CMakeLists.txt +++ b/develop/vendors/CMakeLists.txt @@ -54,6 +54,9 @@ target_include_directories(${PROJECT_NAME}.gbench SYSTEM target_compile_definitions(${PROJECT_NAME}.gbench PUBLIC BENCHMARK_STATIC_DEFINE) +target_link_libraries(${PROJECT_NAME}.gbench + PRIVATE $<$:shlwapi>) + # # vmath.hpp # diff --git a/headers/meta.hpp/meta_binds.hpp b/headers/meta.hpp/meta_binds.hpp index 4290207..f3eb9c8 100644 --- a/headers/meta.hpp/meta_binds.hpp +++ b/headers/meta.hpp/meta_binds.hpp @@ -22,11 +22,6 @@ namespace meta_hpp::detail concept class_bind_destructor_kind // = class_kind && std::is_destructible_v; // - template < typename Base, typename Class > - concept class_bind_base_kind // - = class_kind && class_kind // - && std::derived_from; // - template < typename Member, typename Class > concept class_bind_member_kind // = member_pointer_kind && class_kind // @@ -107,9 +102,6 @@ namespace meta_hpp public: explicit class_bind(metadata_map metadata); - template < detail::class_bind_base_kind... Bases > - class_bind& base_(); - template < typename... Args, typename... Opts > requires detail::class_bind_constructor_kind class_bind& constructor_(Opts&&... opts); diff --git a/headers/meta.hpp/meta_binds/class_bind.hpp b/headers/meta.hpp/meta_binds/class_bind.hpp index 27630f6..e36a55a 100644 --- a/headers/meta.hpp/meta_binds/class_bind.hpp +++ b/headers/meta.hpp/meta_binds/class_bind.hpp @@ -10,83 +10,6 @@ #include "../meta_binds.hpp" #include "../meta_registry.hpp" -namespace meta_hpp::detail::class_bind_impl -{ - using base_upcasts_t = class_type_data::base_upcasts_t; - using deep_upcasts_t = class_type_data::deep_upcasts_t; - - using upcast_func_t = class_type_data::upcast_func_t; - using upcast_func_list_t = class_type_data::upcast_func_list_t; - - using new_bases_db_t = std::vector>; - using deep_upcasts_db_t = std::map>; - using derived_classes_db_t = std::map>; - - template < class_kind Class, class_kind Base > - requires std::is_base_of_v - void update_new_bases_db( // - new_bases_db_t& new_bases_db - ) { - const class_type& new_base = resolve_type(); - - for ( auto&& [db_base, _] : new_bases_db ) { - if ( db_base == new_base ) { - return; - } - } - - new_bases_db.emplace_back( // - new_base, - upcast_func_t{std::in_place_type, std::in_place_type} - ); - } - - inline void update_deep_upcasts_db( // - const class_type& derived_class, - const class_type& new_base_class, - upcast_func_list_t&& derived_to_new_base, - deep_upcasts_db_t& deep_upcasts_db - ) { - const class_type_data& derived_class_data = *type_access(derived_class); - const class_type_data& new_base_class_data = *type_access(new_base_class); - - const auto [deep_upcasts_db_iter, _] = deep_upcasts_db.try_emplace(derived_class, derived_class_data.deep_upcasts); - deep_upcasts_t& derived_deep_upcasts = deep_upcasts_db_iter->second; - - const auto add_derived_deep_upcast = [&derived_deep_upcasts](const class_type& deep_class, upcast_func_list_t&& upcasts) { - auto&& [position, emplaced] = derived_deep_upcasts.try_emplace(deep_class, std::move(upcasts)); - if ( !emplaced ) { - position->second.is_ambiguous = is_disjoint(position->second.vbases, upcasts.vbases); - } - }; - - for ( auto&& [new_deep_class, new_base_to_deep] : new_base_class_data.deep_upcasts ) { - upcast_func_list_t derived_to_new_deep = derived_to_new_base + new_base_to_deep; - add_derived_deep_upcast(new_deep_class, std::move(derived_to_new_deep)); - } - - for ( const class_type& subderived_class : derived_class_data.derived_classes ) { - const class_type_data& subderived_data = *type_access(subderived_class); - upcast_func_t subderived_to_derived = subderived_data.base_upcasts.at(derived_class); - upcast_func_list_t subderived_to_new_base = subderived_to_derived + derived_to_new_base; - update_deep_upcasts_db(subderived_class, new_base_class, std::move(subderived_to_new_base), deep_upcasts_db); - } - - add_derived_deep_upcast(new_base_class, std::move(derived_to_new_base)); - } - - inline void updata_derived_classes_db( // - const class_type& self_class, - const class_type& new_base_class, - derived_classes_db_t& derived_classes_db - ) { - const class_type_data& base_class_data = *type_access(new_base_class); - class_list new_derived_classes{base_class_data.derived_classes}; - insert_or_assign(new_derived_classes, self_class); - derived_classes_db.emplace(new_base_class, std::move(new_derived_classes)); - } -} - namespace meta_hpp { template < detail::class_kind Class > @@ -97,49 +20,6 @@ namespace meta_hpp } } - template < detail::class_kind Class > - template < detail::class_bind_base_kind... Bases > - class_bind& class_bind::base_() { - using namespace detail; - using namespace detail::class_bind_impl; - - new_bases_db_t new_bases_db; - (update_new_bases_db(new_bases_db), ...); - - deep_upcasts_db_t deep_upcasts_db; - derived_classes_db_t derived_classes_db; - - class_list new_base_classes{get_data().base_classes}; - base_upcasts_t new_base_upcasts{get_data().base_upcasts}; - - for ( auto&& [new_base_class, self_to_new_base] : new_bases_db ) { - if ( std::find(new_base_classes.begin(), new_base_classes.end(), new_base_class) != new_base_classes.end() ) { - continue; - } - - update_deep_upcasts_db(*this, new_base_class, self_to_new_base, deep_upcasts_db); - updata_derived_classes_db(*this, new_base_class, derived_classes_db); - - new_base_classes.emplace_back(new_base_class); - new_base_upcasts.emplace(new_base_class, self_to_new_base); - } - - get_data().base_classes.swap(new_base_classes); - get_data().base_upcasts.swap(new_base_upcasts); - - for ( auto&& [derived_class, new_deep_upcasts] : deep_upcasts_db ) { - class_type_data& derived_data = *type_access(derived_class); - derived_data.deep_upcasts.swap(new_deep_upcasts); - } - - for ( auto&& [base_class, new_derived_classes] : derived_classes_db ) { - class_type_data& base_data = *type_access(base_class); - base_data.derived_classes.swap(new_derived_classes); - } - - return *this; - } - template < detail::class_kind Class > template < typename... Args, typename... Opts > requires detail::class_bind_constructor_kind diff --git a/headers/meta.hpp/meta_detail/poly_info.hpp b/headers/meta.hpp/meta_detail/base_info.hpp similarity index 78% rename from headers/meta.hpp/meta_detail/poly_info.hpp rename to headers/meta.hpp/meta_detail/base_info.hpp index c69d830..3f4e79d 100644 --- a/headers/meta.hpp/meta_detail/poly_info.hpp +++ b/headers/meta.hpp/meta_detail/base_info.hpp @@ -18,6 +18,10 @@ namespace meta_hpp::detail class_type type{}; }; + template < typename T > + concept check_base_info_enabled // + = requires { typename T::meta_base_info; }; + template < typename T > concept check_poly_info_enabled // = requires(type_registry& r, const T& v) { @@ -25,7 +29,14 @@ namespace meta_hpp::detail }; } -#define META_HPP_ENABLE_POLY_INFO() \ +#define META_HPP_ENABLE_BASE_INFO(...) \ +public: \ + using meta_base_info = ::meta_hpp::detail::type_list<__VA_ARGS__>; \ +\ +private: + +#define META_HPP_ENABLE_POLY_INFO(...) \ + META_HPP_ENABLE_BASE_INFO(__VA_ARGS__) \ public: \ META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \ virtual ::meta_hpp::detail::poly_info get_most_derived_poly_info(::meta_hpp::detail::type_registry& registry) const { \ diff --git a/headers/meta.hpp/meta_registry.hpp b/headers/meta.hpp/meta_registry.hpp index d96803a..42a6857 100644 --- a/headers/meta.hpp/meta_registry.hpp +++ b/headers/meta.hpp/meta_registry.hpp @@ -10,7 +10,7 @@ #include "meta_states.hpp" #include "meta_types.hpp" -#include "meta_detail/poly_info.hpp" +#include "meta_detail/base_info.hpp" #include "meta_detail/state_registry.hpp" #include "meta_detail/type_registry.hpp" diff --git a/headers/meta.hpp/meta_types.hpp b/headers/meta.hpp/meta_types.hpp index e5e2601..fa10ef7 100644 --- a/headers/meta.hpp/meta_types.hpp +++ b/headers/meta.hpp/meta_types.hpp @@ -211,7 +211,6 @@ namespace meta_hpp [[nodiscard]] const any_type_list& get_argument_types() const noexcept; [[nodiscard]] const class_list& get_base_classes() const noexcept; - [[nodiscard]] const class_list& get_derived_classes() const noexcept; [[nodiscard]] const constructor_list& get_constructors() const noexcept; [[nodiscard]] const destructor_list& get_destructors() const noexcept; [[nodiscard]] const function_list& get_functions() const noexcept; @@ -504,7 +503,6 @@ namespace meta_hpp::detail // NOLINTEND(*-avoid-const-or-ref-data-members) class_list base_classes; - class_list derived_classes; constructor_list constructors; destructor_list destructors; function_list functions; @@ -536,8 +534,8 @@ namespace meta_hpp::detail vbases_t vbases{}; bool is_ambiguous{}; - upcast_func_list_t(const upcast_func_t& _upcast); - upcast_func_list_t(upcasts_t _upcasts, vbases_t _vbases); + 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; diff --git a/headers/meta.hpp/meta_types/class_type.hpp b/headers/meta.hpp/meta_types/class_type.hpp index 0363700..48ee041 100644 --- a/headers/meta.hpp/meta_types/class_type.hpp +++ b/headers/meta.hpp/meta_types/class_type.hpp @@ -26,7 +26,48 @@ namespace meta_hpp::detail , flags{class_traits::make_flags()} , size{class_traits::size} , align{class_traits::align} - , argument_types{resolve_types(typename class_traits::argument_types{})} {} + , argument_types{resolve_types(typename class_traits::argument_types{})} { + if constexpr ( check_base_info_enabled ) { + using meta_base_info = typename Class::meta_base_info; + + [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_class = [&new_base_data](std::in_place_type_t) { + const class_type& base_class = resolve_type(); + const class_type_data& base_class_data = *type_access(base_class); + + upcast_func_t self_to_base{std::in_place_type, std::in_place_type}; + + 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_class_data.deep_upcasts ) { + upcast_func_list_t self_to_deep = self_to_base + 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.emplace(base_class, upcast_func_list_t{self_to_base}); + }; + (add_new_base_class(std::in_place_type>), ...); + + 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>()); + } + } } namespace meta_hpp::detail @@ -50,8 +91,8 @@ namespace meta_hpp::detail namespace meta_hpp::detail { - inline class_type_data::upcast_func_list_t::upcast_func_list_t(const upcast_func_t& _upcast) - : upcasts{_upcast} { + 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); @@ -59,9 +100,9 @@ namespace meta_hpp::detail } } - inline class_type_data::upcast_func_list_t::upcast_func_list_t(upcasts_t _upcasts, vbases_t _vbases) - : upcasts{std::move(_upcasts)} - , vbases{std::move(_vbases)} {} + 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 ) { @@ -88,7 +129,9 @@ namespace meta_hpp::detail new_vbases.insert(l.vbases.begin(), l.vbases.end()); new_vbases.insert(r.vbases.begin(), r.vbases.end()); - return class_type_data::upcast_func_list_t{std::move(new_upcasts), std::move(new_vbases)}; + 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; } } @@ -122,10 +165,6 @@ namespace meta_hpp return data_->base_classes; } - inline const class_list& class_type::get_derived_classes() const noexcept { - return data_->derived_classes; - } - inline const constructor_list& class_type::get_constructors() const noexcept { return data_->constructors; } diff --git a/headers/meta.hpp/meta_ucast/ucast.hpp b/headers/meta.hpp/meta_ucast/ucast.hpp index a28e713..b3d4a75 100644 --- a/headers/meta.hpp/meta_ucast/ucast.hpp +++ b/headers/meta.hpp/meta_ucast/ucast.hpp @@ -9,7 +9,7 @@ #include "../meta_base.hpp" #include "../meta_ucast.hpp" -#include "../meta_detail/poly_info.hpp" +#include "../meta_detail/base_info.hpp" #include "../meta_detail/type_registry.hpp" #include "../meta_detail/value_utilities/utraits.hpp"