new base info wip

This commit is contained in:
BlackMATov
2023-12-25 22:56:21 +07:00
parent 1aea60c686
commit 3148223141
29 changed files with 206 additions and 486 deletions

View File

@@ -9,6 +9,7 @@
- test and support shared libraries - test and support shared libraries
- remove `resolve_poly_type`, use `resolve_type(T&&)` instead - remove `resolve_poly_type`, use `resolve_type(T&&)` instead
- add ucast manual - add ucast manual
- mark all internal macro with DETAIL prefix
## Thoughts ## Thoughts

View File

@@ -21,6 +21,7 @@ namespace
}; };
class rectangle : public shape { class rectangle : public shape {
META_HPP_ENABLE_BASE_INFO(shape)
public: public:
explicit rectangle(int width, int height) explicit rectangle(int width, int height)
: width_{width} : width_{width}
@@ -52,7 +53,6 @@ TEST_CASE("meta/meta_manuals/class/type") {
// 'rectangle' class type registration // 'rectangle' class type registration
meta::class_<rectangle>() meta::class_<rectangle>()
.base_<shape>()
.constructor_<int, int>() .constructor_<int, int>()
.method_("get_width", &rectangle::get_width) .method_("get_width", &rectangle::get_width)
.method_("get_height", &rectangle::get_height); .method_("get_height", &rectangle::get_height);

View File

@@ -21,6 +21,7 @@ namespace
}; };
class rectangle : public shape { class rectangle : public shape {
META_HPP_ENABLE_BASE_INFO(shape)
public: public:
explicit rectangle(int width, int height) explicit rectangle(int width, int height)
: width_{width} : width_{width}
@@ -52,7 +53,6 @@ TEST_CASE("meta/meta_manuals/uvalue") {
// 'rectangle' class type registration // 'rectangle' class type registration
meta::class_<rectangle>() meta::class_<rectangle>()
.base_<shape>()
.constructor_<int, int>() .constructor_<int, int>()
.method_("get_width", &rectangle::get_width) .method_("get_width", &rectangle::get_width)
.method_("get_height", &rectangle::get_height); .method_("get_height", &rectangle::get_height);

View File

@@ -2672,7 +2672,6 @@ namespace meta_hpp
[[nodiscard]] const any_type_list& get_argument_types() const noexcept; [[nodiscard]] const any_type_list& get_argument_types() const noexcept;
[[nodiscard]] const class_list& get_base_classes() 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 constructor_list& get_constructors() const noexcept;
[[nodiscard]] const destructor_list& get_destructors() const noexcept; [[nodiscard]] const destructor_list& get_destructors() const noexcept;
[[nodiscard]] const function_list& get_functions() 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) // NOLINTEND(*-avoid-const-or-ref-data-members)
class_list base_classes; class_list base_classes;
class_list derived_classes;
constructor_list constructors; constructor_list constructors;
destructor_list destructors; destructor_list destructors;
function_list functions; function_list functions;
@@ -2997,8 +2995,8 @@ namespace meta_hpp::detail
vbases_t vbases{}; vbases_t vbases{};
bool is_ambiguous{}; bool is_ambiguous{};
upcast_func_list_t(const upcast_func_t& _upcast); upcast_func_list_t(const upcast_func_t& in_upcast);
upcast_func_list_t(upcasts_t _upcasts, vbases_t _vbases); upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases);
[[nodiscard]] void* apply(void* ptr) const noexcept; [[nodiscard]] void* apply(void* ptr) const noexcept;
[[nodiscard]] const void* apply(const void* ptr) const noexcept; [[nodiscard]] const void* apply(const void* ptr) const noexcept;
@@ -4312,6 +4310,10 @@ namespace meta_hpp::detail
class_type type{}; class_type type{};
}; };
template < typename T >
concept check_base_info_enabled //
= requires { typename T::meta_base_info; };
template < typename T > template < typename T >
concept check_poly_info_enabled // concept check_poly_info_enabled //
= requires(type_registry& r, const T& v) { = 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: \ public: \
META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \ META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \
virtual ::meta_hpp::detail::poly_info get_most_derived_poly_info(::meta_hpp::detail::type_registry& registry) const { \ 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 // concept class_bind_destructor_kind //
= class_kind<Class> && std::is_destructible_v<Class>; // = class_kind<Class> && std::is_destructible_v<Class>; //
template < typename Base, typename Class >
concept class_bind_base_kind //
= class_kind<Base> && class_kind<Class> //
&& std::derived_from<Class, Base>; //
template < typename Member, typename Class > template < typename Member, typename Class >
concept class_bind_member_kind // concept class_bind_member_kind //
= member_pointer_kind<Member> && class_kind<Class> // = member_pointer_kind<Member> && class_kind<Class> //
@@ -4596,9 +4600,6 @@ namespace meta_hpp
public: public:
explicit class_bind(metadata_map metadata); explicit class_bind(metadata_map metadata);
template < detail::class_bind_base_kind<Class>... Bases >
class_bind& base_();
template < typename... Args, typename... Opts > template < typename... Args, typename... Opts >
requires detail::class_bind_constructor_kind<Class, Args...> requires detail::class_bind_constructor_kind<Class, Args...>
class_bind& constructor_(Opts&&... opts); class_bind& constructor_(Opts&&... opts);
@@ -5023,83 +5024,6 @@ namespace meta_hpp
: type_bind_base{resolve_type<Array>(), std::move(metadata)} {} : type_bind_base{resolve_type<Array>(), 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<std::pair<class_type, upcast_func_t>>;
using deep_upcasts_db_t = std::map<class_type, deep_upcasts_t, std::less<>>;
using derived_classes_db_t = std::map<class_type, class_list, std::less<>>;
template < class_kind Class, class_kind Base >
requires std::is_base_of_v<Base, Class>
void update_new_bases_db( //
new_bases_db_t& new_bases_db
) {
const class_type& new_base = resolve_type<Base>();
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<Class>, std::in_place_type<Base>}
);
}
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 namespace meta_hpp
{ {
template < detail::class_kind Class > template < detail::class_kind Class >
@@ -5110,49 +5034,6 @@ namespace meta_hpp
} }
} }
template < detail::class_kind Class >
template < detail::class_bind_base_kind<Class>... Bases >
class_bind<Class>& class_bind<Class>::base_() {
using namespace detail;
using namespace detail::class_bind_impl;
new_bases_db_t new_bases_db;
(update_new_bases_db<Class, Bases>(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 < detail::class_kind Class >
template < typename... Args, typename... Opts > template < typename... Args, typename... Opts >
requires detail::class_bind_constructor_kind<Class, Args...> requires detail::class_bind_constructor_kind<Class, Args...>
@@ -8476,7 +8357,48 @@ namespace meta_hpp::detail
, flags{class_traits<Class>::make_flags()} , flags{class_traits<Class>::make_flags()}
, size{class_traits<Class>::size} , size{class_traits<Class>::size}
, align{class_traits<Class>::align} , align{class_traits<Class>::align}
, argument_types{resolve_types(typename class_traits<Class>::argument_types{})} {} , argument_types{resolve_types(typename class_traits<Class>::argument_types{})} {
if constexpr ( check_base_info_enabled<Class> ) {
using meta_base_info = typename Class::meta_base_info;
[this]<std::size_t... Is>(std::index_sequence<Is...>) {
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]<class_kind Base>(std::in_place_type_t<Base>) {
const class_type& base_class = resolve_type<Base>();
const class_type_data& base_class_data = *type_access(base_class);
upcast_func_t self_to_base{std::in_place_type<Class>, std::in_place_type<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_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<type_list_at_t<Is, meta_base_info>>), ...);
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<type_list_arity_v<meta_base_info>>());
}
}
} }
namespace meta_hpp::detail namespace meta_hpp::detail
@@ -8500,8 +8422,8 @@ namespace meta_hpp::detail
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) inline class_type_data::upcast_func_list_t::upcast_func_list_t(const upcast_func_t& in_upcast)
: upcasts{_upcast} { : upcasts{in_upcast} {
for ( const upcast_func_t& upcast : upcasts ) { for ( const upcast_func_t& upcast : upcasts ) {
if ( upcast.is_virtual ) { if ( upcast.is_virtual ) {
vbases.emplace(upcast.target); 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) inline class_type_data::upcast_func_list_t::upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases)
: upcasts{std::move(_upcasts)} : upcasts{std::move(in_upcasts)}
, vbases{std::move(_vbases)} {} , vbases{std::move(in_vbases)} {}
inline void* class_type_data::upcast_func_list_t::apply(void* ptr) const noexcept { inline void* class_type_data::upcast_func_list_t::apply(void* ptr) const noexcept {
for ( const upcast_func_t& upcast : upcasts ) { 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(l.vbases.begin(), l.vbases.end());
new_vbases.insert(r.vbases.begin(), r.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; 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 { inline const constructor_list& class_type::get_constructors() const noexcept {
return data_->constructors; return data_->constructors;
} }

View File

@@ -28,14 +28,17 @@ namespace
struct base2 : base1 { struct base2 : base1 {
unsigned b2{2}; unsigned b2{2};
META_HPP_ENABLE_BASE_INFO(base1)
}; };
struct base3 : base2 { struct base3 : base2 {
unsigned b3{3}; unsigned b3{3};
META_HPP_ENABLE_BASE_INFO(base2)
}; };
struct base4 : base3 { struct base4 : base3 {
unsigned b4{4}; unsigned b4{4};
META_HPP_ENABLE_BASE_INFO(base3)
}; };
unsigned static_function_1(base1* b1) { unsigned static_function_1(base1* b1) {
@@ -67,14 +70,6 @@ namespace
static_acc = 0; static_acc = 0;
} }
const bool registered = [](){
meta::class_<base1>();
meta::class_<base2>().base_<base1>();
meta::class_<base3>().base_<base2>();
meta::class_<base4>().base_<base3>();
return true;
}();
meta::scope meta_bench_scope = meta::local_scope_("") meta::scope meta_bench_scope = meta::local_scope_("")
.function_("cast_function_1", &static_function_1) .function_("cast_function_1", &static_function_1)
.function_("cast_function_2", &static_function_2) .function_("cast_function_2", &static_function_2)

View File

@@ -28,17 +28,17 @@ namespace
struct base2 : base1 { struct base2 : base1 {
unsigned b2{2}; unsigned b2{2};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(base1)
}; };
struct base3 : base2 { struct base3 : base2 {
unsigned b3{3}; unsigned b3{3};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(base2)
}; };
struct base4 : base3 { struct base4 : base3 {
unsigned b4{4}; unsigned b4{4};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(base3)
}; };
base4* dynamic_cast_1(base1* b1) { base4* dynamic_cast_1(base1* b1) {
@@ -56,14 +56,6 @@ namespace
base4* dynamic_cast_4(base4* b4) { base4* dynamic_cast_4(base4* b4) {
return dynamic_cast<base4*>(b4); return dynamic_cast<base4*>(b4);
} }
const bool registered = [](){
meta::class_<base1>();
meta::class_<base2>().base_<base1>();
meta::class_<base3>().base_<base2>();
meta::class_<base4>().base_<base3>();
return true;
}();
} }
// //

View File

@@ -10,29 +10,25 @@
namespace namespace
{ {
struct A1 { std::string a1{"a1"}; }; struct A1 { std::string a1{"a1"}; };
struct B1 : A1 { std::string b1{"b1"}; }; struct B1 : A1 { std::string b1{"b1"}; META_HPP_ENABLE_BASE_INFO(A1) };
struct C1 : A1 { std::string c1{"c1"}; }; struct C1 : A1 { std::string c1{"c1"}; META_HPP_ENABLE_BASE_INFO(A1) };
struct D1 : B1, C1 { std::string d1{"d1"}; }; struct D1 : B1, C1 { std::string d1{"d1"}; META_HPP_ENABLE_BASE_INFO(B1, C1) };
struct A2 { std::string a2{"a2"}; }; struct A2 { std::string a2{"a2"}; };
struct B2 : virtual A2 { std::string b2{"b2"}; }; struct B2 : virtual A2 { std::string b2{"b2"}; META_HPP_ENABLE_BASE_INFO(A2) };
struct C2 : virtual A2 { std::string c2{"c2"}; }; struct C2 : virtual A2 { std::string c2{"c2"}; META_HPP_ENABLE_BASE_INFO(A2) };
struct D2 : B2, C2 { std::string d2{"d2"}; }; struct D2 : B2, C2 { std::string d2{"d2"}; META_HPP_ENABLE_BASE_INFO(B2, C2) };
struct A3 { std::string a3{"a3"}; }; struct A3 { std::string a3{"a3"}; };
struct B3 : virtual A3 { std::string b3{"b3"}; }; struct B3 : virtual A3 { std::string b3{"b3"}; META_HPP_ENABLE_BASE_INFO(A3) };
struct C3 : A3 { std::string c3{"c3"}; }; struct C3 : A3 { std::string c3{"c3"}; META_HPP_ENABLE_BASE_INFO(A3) };
struct D3 : B3, C3 { std::string d3{"d3"}; }; struct D3 : B3, C3 { std::string d3{"d3"}; META_HPP_ENABLE_BASE_INFO(B3, C3) };
} }
TEST_CASE("meta/meta_features/ambiguous") { TEST_CASE("meta/meta_features/ambiguous") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
{ {
meta::class_<B1>().base_<A1>();
meta::class_<C1>().base_<A1>();
meta::class_<D1>().base_<B1, C1>();
// A1 < B1 // A1 < B1
// < D1 // < D1
// A1 < C1 // A1 < C1
@@ -56,10 +52,6 @@ TEST_CASE("meta/meta_features/ambiguous") {
} }
{ {
meta::class_<B2>().base_<A2>();
meta::class_<C2>().base_<A2>();
meta::class_<D2>().base_<B2, C2>();
// A2 <= B2 // A2 <= B2
// < D2 // < D2
// A2 <= C2 // A2 <= C2
@@ -83,10 +75,6 @@ TEST_CASE("meta/meta_features/ambiguous") {
} }
{ {
meta::class_<B3>().base_<A3>();
meta::class_<C3>().base_<A3>();
meta::class_<D3>().base_<B3, C3>();
// A3 <= B3 // A3 <= B3
// < D3 // < D3
// A3 < C3 // A3 < C3

View File

@@ -22,9 +22,9 @@ namespace
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO()
}; };
struct B : virtual A { META_HPP_ENABLE_POLY_INFO() }; struct B : virtual A { META_HPP_ENABLE_POLY_INFO(A) };
struct C : virtual A { META_HPP_ENABLE_POLY_INFO() }; struct C : virtual A { META_HPP_ENABLE_POLY_INFO(A) };
struct D : B, C { META_HPP_ENABLE_POLY_INFO() }; struct D : B, C { META_HPP_ENABLE_POLY_INFO(B, C) };
struct E {}; struct E {};
} }
@@ -35,12 +35,6 @@ TEST_CASE("meta/meta_features/diamond") {
using meta::detail::type_registry; using meta::detail::type_registry;
type_registry& r{type_registry::instance()}; type_registry& r{type_registry::instance()};
meta::class_<A>();
meta::class_<B>().base_<A>();
meta::class_<C>().base_<A>();
meta::class_<D>().base_<B>().base_<C>();
meta::class_<E>();
// * <- B <- * // * <- B <- *
// A D // A D
// * <- C <- * // * <- C <- *

View File

@@ -10,31 +10,21 @@
namespace namespace
{ {
struct A { std::string a{"a"}; }; struct A { std::string a{"a"}; };
struct B0 : virtual A { std::string b0{"b0"}; }; struct B0 : virtual A { std::string b0{"b0"}; META_HPP_ENABLE_BASE_INFO(A) };
struct B1 : virtual A { std::string b1{"b1"}; }; 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 D0 : C { std::string d0{"d0"}; META_HPP_ENABLE_BASE_INFO(C) };
struct E0 : D0 { std::string e0{"e0"}; }; struct E0 : D0 { std::string e0{"e0"}; META_HPP_ENABLE_BASE_INFO(D0) };
struct D1 : C { std::string d1{"d1"}; }; struct D1 : C { std::string d1{"d1"}; META_HPP_ENABLE_BASE_INFO(C) };
struct E1 : D1 { std::string e1{"e1"}; }; struct E1 : D1 { std::string e1{"e1"}; META_HPP_ENABLE_BASE_INFO(D1) };
} }
TEST_CASE("meta/meta_features/multiple2/_") { TEST_CASE("meta/meta_features/multiple2/_") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
meta::class_<C>().base_<B0, B1>();
meta::class_<B0>().base_<A>();
meta::class_<B1>().base_<A>();
meta::class_<E0>().base_<D0>();
meta::class_<E1>().base_<D1>();
meta::class_<D0>().base_<C>();
meta::class_<D1>().base_<C>();
// * <- B0 <- * * <- D0 * <- E0 // * <- B0 <- * * <- D0 * <- E0
// A C // A C
// * <- B1 <- * * <- D1 * <- E1 // * <- B1 <- * * <- D1 * <- E1

View File

@@ -21,22 +21,16 @@ namespace
virtual ~A() = default; virtual ~A() = default;
}; };
struct B : A {}; struct B : A { META_HPP_ENABLE_BASE_INFO(A) };
struct C : A {}; struct C : A { META_HPP_ENABLE_BASE_INFO(A) };
struct D : B, C {}; struct D : B, C { META_HPP_ENABLE_BASE_INFO(B, C) };
struct E : D {}; struct E : D { META_HPP_ENABLE_BASE_INFO(D) };
struct F {}; struct F {};
} }
TEST_CASE("meta/meta_features/multiple/_") { TEST_CASE("meta/meta_features/multiple/_") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
meta::class_<D>().base_<B, C>();
meta::class_<E>().base_<D>();
meta::class_<B>().base_<A>();
meta::class_<C>().base_<A>();
// A * <- B <- * // A * <- B <- *
// D * <- E // D * <- E
// A * <- C <- * // A * <- C <- *

View File

@@ -10,43 +10,38 @@
namespace namespace
{ {
struct A1 {}; struct A1 {};
struct B1 : A1 {}; struct B1 : A1 { META_HPP_ENABLE_BASE_INFO(A1) };
struct C1 : A1 {}; struct C1 : A1 { META_HPP_ENABLE_BASE_INFO(A1) };
struct D1 : B1, C1 {}; struct D1 : B1, C1 { META_HPP_ENABLE_BASE_INFO(B1, C1) };
// A1 <- B1 <- * // A1 <- B1 <- *
// D1 // D1
// A1 <- C1 <- * // A1 <- C1 <- *
struct A2 {}; struct A2 {};
struct B2 : virtual A2 {}; struct B2 : virtual A2 { META_HPP_ENABLE_BASE_INFO(A2) };
struct C2 : virtual B2 {}; struct C2 : virtual B2 { META_HPP_ENABLE_BASE_INFO(B2) };
struct D2 : virtual B2 {}; struct D2 : virtual B2 { META_HPP_ENABLE_BASE_INFO(B2) };
struct E2 : C2, D2 {}; struct E2 : C2, D2 { META_HPP_ENABLE_BASE_INFO(C2, D2) };
// A2 <= B2 <= C2 <- * // A2 <= B2 <= C2 <- *
// E2 // E2
// A2 <= B2 <= D2 <- * // A2 <= B2 <= D2 <- *
struct A3 {}; struct A3 {};
struct B3 : virtual A3 {}; struct B3 : virtual A3 { META_HPP_ENABLE_BASE_INFO(A3) };
struct C3 : A3 {}; struct C3 : A3 { META_HPP_ENABLE_BASE_INFO(A3) };
struct D3 : B3, C3 {}; struct D3 : B3, C3 { META_HPP_ENABLE_BASE_INFO(B3, C3) };
// A3 <= B3 <- * // A3 <= B3 <- *
// D3 // D3
// A3 <- C3 <- * // A3 <- C3 <- *
} }
TEST_CASE("meta/meta_issues/random/1") { TEST_CASE("meta/meta_issues/random/1") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
{ {
meta::class_<B1>().base_<A1>();
meta::class_<C1>().base_<A1>();
meta::class_<D1>().base_<B1, C1>();
CHECK(meta::is_invocable_with(+[](const D1&){ return true; }, D1{})); 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 C1&){ return true; }, D1{}));
CHECK(meta::is_invocable_with(+[](const B1&){ 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_<B2>().base_<A2>();
meta::class_<C2>().base_<B2>();
meta::class_<D2>().base_<B2>();
meta::class_<E2>().base_<C2, D2>();
CHECK(meta::is_invocable_with(+[](const A2&){ return true; }, E2{})); 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 B2&){ return true; }, E2{}));
CHECK(meta::is_invocable_with(+[](const C2&){ 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_<B3>().base_<A3>();
meta::class_<C3>().base_<A3>();
meta::class_<D3>().base_<B3, C3>();
static_assert(std::is_invocable_v<void(A3*), A3*>); static_assert(std::is_invocable_v<void(A3*), A3*>);
static_assert(std::is_invocable_v<void(A3*), B3*>); static_assert(std::is_invocable_v<void(A3*), B3*>);
static_assert(std::is_invocable_v<void(A3*), C3*>); static_assert(std::is_invocable_v<void(A3*), C3*>);

View File

@@ -53,10 +53,15 @@ namespace
// //
int ii = 0; int ii = 0;
//
META_HPP_ENABLE_BASE_INFO(base)
}; };
struct derived_clazz : fake, clazz { struct derived_clazz : fake, clazz {
int pure_virtual_method() override { return -2; } int pure_virtual_method() override { return -2; }
META_HPP_ENABLE_BASE_INFO(fake, clazz)
}; };
struct clazz2 {}; struct clazz2 {};
@@ -69,8 +74,6 @@ TEST_CASE("meta/meta_states/method/_") {
.method_("pure_virtual_method", &base::pure_virtual_method); .method_("pure_virtual_method", &base::pure_virtual_method);
meta::class_<clazz>() meta::class_<clazz>()
.base_<base>()
.method_("non_const_method", &clazz::non_const_method) .method_("non_const_method", &clazz::non_const_method)
.method_("non_const_method_noexcept", &clazz::non_const_method_noexcept) .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_rref", &clazz::const_method_rref)
.method_("const_method_noexcept_rref", &clazz::const_method_noexcept_rref); .method_("const_method_noexcept_rref", &clazz::const_method_noexcept_rref);
meta::class_<derived_clazz>()
.base_<clazz>();
} }
TEST_CASE("meta/meta_states/method") { TEST_CASE("meta/meta_states/method") {

View File

@@ -49,10 +49,12 @@ namespace
static double derived_function() { return 3.0; } static double derived_function() { return 3.0; }
static constexpr double derived_variable = 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 { struct final_derived_clazz final : derived_clazz {
using derived_clazz::derived_clazz; using derived_clazz::derived_clazz;
META_HPP_ENABLE_BASE_INFO(derived_clazz)
}; };
template < typename... Args > template < typename... Args >
@@ -64,7 +66,6 @@ TEST_CASE("meta/meta_types/class_type/_") {
meta::class_<base_clazz_1>() meta::class_<base_clazz_1>()
.constructor_<int>() .constructor_<int>()
.base_<>()
.member_("base_member_1", &base_clazz_1::base_member_1) .member_("base_member_1", &base_clazz_1::base_member_1)
.method_("base_method_1", &base_clazz_1::base_method_1) .method_("base_method_1", &base_clazz_1::base_method_1)
.function_("base_function_1", &base_clazz_1::base_function_1) .function_("base_function_1", &base_clazz_1::base_function_1)
@@ -83,15 +84,13 @@ TEST_CASE("meta/meta_types/class_type/_") {
meta::class_<derived_clazz>() meta::class_<derived_clazz>()
.constructor_<int, float>() .constructor_<int, float>()
.base_<base_clazz_1, base_clazz_2>()
.member_("derived_member", &derived_clazz::derived_member) .member_("derived_member", &derived_clazz::derived_member)
.method_("derived_method", &derived_clazz::derived_method) .method_("derived_method", &derived_clazz::derived_method)
.function_("derived_function", &derived_clazz::derived_function) .function_("derived_function", &derived_clazz::derived_function)
.variable_("derived_variable", &derived_clazz::derived_variable); .variable_("derived_variable", &derived_clazz::derived_variable);
meta::class_<final_derived_clazz>() meta::class_<final_derived_clazz>()
.constructor_<int, float>() .constructor_<int, float>();
.base_<derived_clazz>();
} }
TEST_CASE("meta/meta_types/class_type") { 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}); 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") { SUBCASE("get_functions") {
CHECK(base_clazz_1_type.get_functions().size() == 3); CHECK(base_clazz_1_type.get_functions().size() == 3);
CHECK(base_clazz_2_type.get_functions().size() == 1); CHECK(base_clazz_2_type.get_functions().size() == 1);

View File

@@ -32,16 +32,19 @@ namespace
struct B : virtual A { struct B : virtual A {
int bi = 2; int bi = 2;
[[nodiscard]] int f() const { return bi; } [[nodiscard]] int f() const { return bi; }
META_HPP_ENABLE_BASE_INFO(A)
}; };
struct C : virtual A { struct C : virtual A {
int ci = 3; int ci = 3;
[[nodiscard]] int f() const { return ci; } [[nodiscard]] int f() const { return ci; }
META_HPP_ENABLE_BASE_INFO(A)
}; };
struct D : B, C { struct D : B, C {
int di = 4; int di = 4;
[[nodiscard]] int f() const { return di; } [[nodiscard]] int f() const { return di; }
META_HPP_ENABLE_BASE_INFO(B, C)
}; };
} }
@@ -51,11 +54,6 @@ TEST_CASE("meta/meta_utilities/arg2") {
// * <- B <- * // * <- B <- *
// A D // A D
// * <- C <- * // * <- C <- *
meta::class_<A>();
meta::class_<B>().base_<A>();
meta::class_<C>().base_<A>();
meta::class_<D>().base_<B>().base_<C>();
} }
TEST_CASE("meta/meta_utilities/arg2/cast") { TEST_CASE("meta/meta_utilities/arg2/cast") {

View File

@@ -25,16 +25,19 @@ namespace
struct B : virtual A { struct B : virtual A {
int bi = 2; int bi = 2;
[[nodiscard]] int f() const { return bi; } [[nodiscard]] int f() const { return bi; }
META_HPP_ENABLE_BASE_INFO(A)
}; };
struct C : virtual A { struct C : virtual A {
int ci = 3; int ci = 3;
[[nodiscard]] int f() const { return ci; } [[nodiscard]] int f() const { return ci; }
META_HPP_ENABLE_BASE_INFO(A)
}; };
struct D : B, C { struct D : B, C {
int di = 4; int di = 4;
[[nodiscard]] int f() const { return di; } [[nodiscard]] int f() const { return di; }
META_HPP_ENABLE_BASE_INFO(B, C)
}; };
} }
@@ -44,11 +47,6 @@ TEST_CASE("meta/meta_utilities/arg3") {
// * <- B <- * // * <- B <- *
// A D // A D
// * <- C <- * // * <- C <- *
meta::class_<A>();
meta::class_<B>().base_<A>();
meta::class_<C>().base_<A>();
meta::class_<D>().base_<B>().base_<C>();
} }
TEST_CASE("meta/meta_utilities/arg3/cast") { TEST_CASE("meta/meta_utilities/arg3/cast") {

View File

@@ -23,14 +23,17 @@ namespace
struct B : virtual A { struct B : virtual A {
int bi = 2; int bi = 2;
META_HPP_ENABLE_BASE_INFO(A)
}; };
struct C : virtual A { struct C : virtual A {
int ci = 3; int ci = 3;
META_HPP_ENABLE_BASE_INFO(A)
}; };
struct D : B, C { struct D : B, C {
int di = 4; int di = 4;
META_HPP_ENABLE_BASE_INFO(B, C)
}; };
} }
@@ -40,11 +43,6 @@ TEST_CASE("meta/meta_utilities/arg5") {
// * <- B <- * // * <- B <- *
// A D // A D
// * <- C <- * // * <- C <- *
meta::class_<A>();
meta::class_<B>().base_<A>();
meta::class_<C>().base_<A>();
meta::class_<D>().base_<B>().base_<C>();
} }
TEST_CASE("meta/meta_utilities/arg5/cast") { TEST_CASE("meta/meta_utilities/arg5/cast") {

View File

@@ -40,11 +40,6 @@ TEST_CASE("meta/meta_utilities/arg7") {
// * <- B <- * // * <- B <- *
// A D // A D
// * <- C <- * // * <- C <- *
meta::class_<A>();
meta::class_<B>().base_<A>();
meta::class_<C>().base_<A>();
meta::class_<D>().base_<B>().base_<C>();
} }
TEST_CASE("meta/meta_utilities/arg7/cast/to_void") { TEST_CASE("meta/meta_utilities/arg7/cast/to_void") {

View File

@@ -21,6 +21,7 @@ namespace
}; };
struct dclazz : fake, clazz { struct dclazz : fake, clazz {
META_HPP_ENABLE_BASE_INFO(fake, clazz)
}; };
int f1(int v) { return v; } int f1(int v) { return v; }
@@ -110,14 +111,6 @@ namespace
}\ }\
} }
TEST_CASE("meta/meta_utilities/arg") {
namespace meta = meta_hpp;
meta::class_<fake>();
meta::class_<clazz>();
meta::class_<dclazz>().base_<fake>().base_<clazz>();
}
TEST_CASE("meta/meta_utilities/arg/refs") { TEST_CASE("meta/meta_utilities/arg/refs") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
using meta::detail::uarg; using meta::detail::uarg;

View File

@@ -21,14 +21,14 @@ namespace
B1() = default; B1() = default;
B1(const B1&) = default; B1(const B1&) = default;
char b{'b'}; char b{'b'};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(A1)
}; };
struct C1 : B1 { struct C1 : B1 {
C1() = default; C1() = default;
C1(const C1&) = default; C1(const C1&) = default;
char c{'c'}; char c{'c'};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(B1)
}; };
// A1 <- B1 <- C1 // A1 <- B1 <- C1
@@ -45,14 +45,14 @@ namespace
B2() = default; B2() = default;
B2(const B2&) = default; B2(const B2&) = default;
char b{'b'}; char b{'b'};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(A2)
}; };
struct C2 : virtual A2 { struct C2 : virtual A2 {
C2() = default; C2() = default;
C2(const C2&) = default; C2(const C2&) = default;
char c{'c'}; char c{'c'};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(A2)
}; };
@@ -68,14 +68,14 @@ namespace
E2() = default; E2() = default;
E2(const E2&) = default; E2(const E2&) = default;
char e{'e'}; char e{'e'};
META_HPP_ENABLE_POLY_INFO() META_HPP_ENABLE_POLY_INFO(D2)
}; };
struct F2 : B2, C2, E2 { struct F2 : B2, C2, E2 {
F2() = default; F2() = default;
F2(const F2&) = default; F2(const F2&) = default;
char f{'f'}; 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_<A1>();
meta::class_<B1>().base_<A1>();
meta::class_<C1>().base_<B1>();
meta::class_<A2>();
meta::class_<B2>().base_<A2>();
meta::class_<C2>().base_<A2>();
meta::class_<D2>();
meta::class_<E2>().base_<D2>();
meta::class_<F2>().base_<B2, C2, E2>();
}
TEST_CASE("meta/meta_utilities/ucast") { TEST_CASE("meta/meta_utilities/ucast") {
namespace meta = meta_hpp; namespace meta = meta_hpp;

View File

@@ -23,7 +23,9 @@ namespace
[[nodiscard]] int m6() const && { return ii; } [[nodiscard]] int m6() const && { return ii; }
}; };
struct dclazz : fake, clazz {}; struct dclazz : fake, clazz {
META_HPP_ENABLE_BASE_INFO(fake, clazz)
};
} }
// NOLINTNEXTLINE(*-macro-usage) // NOLINTNEXTLINE(*-macro-usage)
@@ -70,14 +72,6 @@ namespace
}\ }\
} }
TEST_CASE("meta/meta_utilities/inst2") {
namespace meta = meta_hpp;
meta::class_<fake>();
meta::class_<clazz>();
meta::class_<dclazz>().base_<fake>().base_<clazz>();
}
TEST_CASE("meta/meta_utilities/inst2/refs") { TEST_CASE("meta/meta_utilities/inst2/refs") {
namespace meta = meta_hpp; namespace meta = meta_hpp;
using meta::detail::uarg; using meta::detail::uarg;

View File

@@ -15,41 +15,25 @@ namespace
struct base1 : virtual base0 { struct base1 : virtual base0 {
int j{42}; int j{42};
META_HPP_ENABLE_BASE_INFO(base0)
}; };
struct base2 : virtual base0 { struct base2 : virtual base0 {
int k{84}; int k{84};
META_HPP_ENABLE_BASE_INFO(base0)
}; };
struct derived : base1, base2 { struct derived : base1, base2 {
int l{168}; int l{168};
META_HPP_ENABLE_BASE_INFO(base1, base2)
}; };
struct derived2 : base1, base2 { struct derived2 : base1, base2 {
int m{336}; int m{336};
META_HPP_ENABLE_BASE_INFO(base1, base2)
}; };
} }
TEST_CASE("meta/meta_utilities/value3") {
namespace meta = meta_hpp;
meta::class_<base0>();
meta::class_<base1>()
.base_<base0>();
meta::class_<base2>()
.base_<base0>();
meta::class_<derived>()
.base_<base1>()
.base_<base2>();
meta::class_<derived2>()
.base_<base1>()
.base_<base2>();
}
TEST_CASE("meta/meta_utilities/value3/get_type") { TEST_CASE("meta/meta_utilities/value3/get_type") {
namespace meta = meta_hpp; namespace meta = meta_hpp;

View File

@@ -54,6 +54,9 @@ target_include_directories(${PROJECT_NAME}.gbench SYSTEM
target_compile_definitions(${PROJECT_NAME}.gbench target_compile_definitions(${PROJECT_NAME}.gbench
PUBLIC BENCHMARK_STATIC_DEFINE) PUBLIC BENCHMARK_STATIC_DEFINE)
target_link_libraries(${PROJECT_NAME}.gbench
PRIVATE $<$<PLATFORM_ID:Windows>:shlwapi>)
# #
# vmath.hpp # vmath.hpp
# #

View File

@@ -22,11 +22,6 @@ namespace meta_hpp::detail
concept class_bind_destructor_kind // concept class_bind_destructor_kind //
= class_kind<Class> && std::is_destructible_v<Class>; // = class_kind<Class> && std::is_destructible_v<Class>; //
template < typename Base, typename Class >
concept class_bind_base_kind //
= class_kind<Base> && class_kind<Class> //
&& std::derived_from<Class, Base>; //
template < typename Member, typename Class > template < typename Member, typename Class >
concept class_bind_member_kind // concept class_bind_member_kind //
= member_pointer_kind<Member> && class_kind<Class> // = member_pointer_kind<Member> && class_kind<Class> //
@@ -107,9 +102,6 @@ namespace meta_hpp
public: public:
explicit class_bind(metadata_map metadata); explicit class_bind(metadata_map metadata);
template < detail::class_bind_base_kind<Class>... Bases >
class_bind& base_();
template < typename... Args, typename... Opts > template < typename... Args, typename... Opts >
requires detail::class_bind_constructor_kind<Class, Args...> requires detail::class_bind_constructor_kind<Class, Args...>
class_bind& constructor_(Opts&&... opts); class_bind& constructor_(Opts&&... opts);

View File

@@ -10,83 +10,6 @@
#include "../meta_binds.hpp" #include "../meta_binds.hpp"
#include "../meta_registry.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<std::pair<class_type, upcast_func_t>>;
using deep_upcasts_db_t = std::map<class_type, deep_upcasts_t, std::less<>>;
using derived_classes_db_t = std::map<class_type, class_list, std::less<>>;
template < class_kind Class, class_kind Base >
requires std::is_base_of_v<Base, Class>
void update_new_bases_db( //
new_bases_db_t& new_bases_db
) {
const class_type& new_base = resolve_type<Base>();
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<Class>, std::in_place_type<Base>}
);
}
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 namespace meta_hpp
{ {
template < detail::class_kind Class > template < detail::class_kind Class >
@@ -97,49 +20,6 @@ namespace meta_hpp
} }
} }
template < detail::class_kind Class >
template < detail::class_bind_base_kind<Class>... Bases >
class_bind<Class>& class_bind<Class>::base_() {
using namespace detail;
using namespace detail::class_bind_impl;
new_bases_db_t new_bases_db;
(update_new_bases_db<Class, Bases>(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 < detail::class_kind Class >
template < typename... Args, typename... Opts > template < typename... Args, typename... Opts >
requires detail::class_bind_constructor_kind<Class, Args...> requires detail::class_bind_constructor_kind<Class, Args...>

View File

@@ -18,6 +18,10 @@ namespace meta_hpp::detail
class_type type{}; class_type type{};
}; };
template < typename T >
concept check_base_info_enabled //
= requires { typename T::meta_base_info; };
template < typename T > template < typename T >
concept check_poly_info_enabled // concept check_poly_info_enabled //
= requires(type_registry& r, const T& v) { = 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: \ public: \
META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \ META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \
virtual ::meta_hpp::detail::poly_info get_most_derived_poly_info(::meta_hpp::detail::type_registry& registry) const { \ virtual ::meta_hpp::detail::poly_info get_most_derived_poly_info(::meta_hpp::detail::type_registry& registry) const { \

View File

@@ -10,7 +10,7 @@
#include "meta_states.hpp" #include "meta_states.hpp"
#include "meta_types.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/state_registry.hpp"
#include "meta_detail/type_registry.hpp" #include "meta_detail/type_registry.hpp"

View File

@@ -211,7 +211,6 @@ namespace meta_hpp
[[nodiscard]] const any_type_list& get_argument_types() const noexcept; [[nodiscard]] const any_type_list& get_argument_types() const noexcept;
[[nodiscard]] const class_list& get_base_classes() 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 constructor_list& get_constructors() const noexcept;
[[nodiscard]] const destructor_list& get_destructors() const noexcept; [[nodiscard]] const destructor_list& get_destructors() const noexcept;
[[nodiscard]] const function_list& get_functions() 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) // NOLINTEND(*-avoid-const-or-ref-data-members)
class_list base_classes; class_list base_classes;
class_list derived_classes;
constructor_list constructors; constructor_list constructors;
destructor_list destructors; destructor_list destructors;
function_list functions; function_list functions;
@@ -536,8 +534,8 @@ namespace meta_hpp::detail
vbases_t vbases{}; vbases_t vbases{};
bool is_ambiguous{}; bool is_ambiguous{};
upcast_func_list_t(const upcast_func_t& _upcast); upcast_func_list_t(const upcast_func_t& in_upcast);
upcast_func_list_t(upcasts_t _upcasts, vbases_t _vbases); upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases);
[[nodiscard]] void* apply(void* ptr) const noexcept; [[nodiscard]] void* apply(void* ptr) const noexcept;
[[nodiscard]] const void* apply(const void* ptr) const noexcept; [[nodiscard]] const void* apply(const void* ptr) const noexcept;

View File

@@ -26,7 +26,48 @@ namespace meta_hpp::detail
, flags{class_traits<Class>::make_flags()} , flags{class_traits<Class>::make_flags()}
, size{class_traits<Class>::size} , size{class_traits<Class>::size}
, align{class_traits<Class>::align} , align{class_traits<Class>::align}
, argument_types{resolve_types(typename class_traits<Class>::argument_types{})} {} , argument_types{resolve_types(typename class_traits<Class>::argument_types{})} {
if constexpr ( check_base_info_enabled<Class> ) {
using meta_base_info = typename Class::meta_base_info;
[this]<std::size_t... Is>(std::index_sequence<Is...>) {
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]<class_kind Base>(std::in_place_type_t<Base>) {
const class_type& base_class = resolve_type<Base>();
const class_type_data& base_class_data = *type_access(base_class);
upcast_func_t self_to_base{std::in_place_type<Class>, std::in_place_type<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_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<type_list_at_t<Is, meta_base_info>>), ...);
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<type_list_arity_v<meta_base_info>>());
}
}
} }
namespace meta_hpp::detail namespace meta_hpp::detail
@@ -50,8 +91,8 @@ namespace meta_hpp::detail
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) inline class_type_data::upcast_func_list_t::upcast_func_list_t(const upcast_func_t& in_upcast)
: upcasts{_upcast} { : upcasts{in_upcast} {
for ( const upcast_func_t& upcast : upcasts ) { for ( const upcast_func_t& upcast : upcasts ) {
if ( upcast.is_virtual ) { if ( upcast.is_virtual ) {
vbases.emplace(upcast.target); 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) inline class_type_data::upcast_func_list_t::upcast_func_list_t(upcasts_t in_upcasts, vbases_t in_vbases)
: upcasts{std::move(_upcasts)} : upcasts{std::move(in_upcasts)}
, vbases{std::move(_vbases)} {} , vbases{std::move(in_vbases)} {}
inline void* class_type_data::upcast_func_list_t::apply(void* ptr) const noexcept { inline void* class_type_data::upcast_func_list_t::apply(void* ptr) const noexcept {
for ( const upcast_func_t& upcast : upcasts ) { 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(l.vbases.begin(), l.vbases.end());
new_vbases.insert(r.vbases.begin(), r.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; 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 { inline const constructor_list& class_type::get_constructors() const noexcept {
return data_->constructors; return data_->constructors;
} }

View File

@@ -9,7 +9,7 @@
#include "../meta_base.hpp" #include "../meta_base.hpp"
#include "../meta_ucast.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/type_registry.hpp"
#include "../meta_detail/value_utilities/utraits.hpp" #include "../meta_detail/value_utilities/utraits.hpp"