mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-16 14:09:02 +07:00
fix deep is_base_of and is_derived_from
This commit is contained in:
@@ -23,6 +23,7 @@ namespace meta_hpp
|
||||
template < class_kind Class >
|
||||
template < typename... Args >
|
||||
class_bind<Class>& class_bind<Class>::ctor_() {
|
||||
static_assert(std::is_constructible_v<Class, Args...>);
|
||||
auto ctor_state = detail::ctor_state::make<Class, Args...>();
|
||||
data_->ctors.emplace(ctor_state->index, std::move(ctor_state));
|
||||
return *this;
|
||||
@@ -31,6 +32,7 @@ namespace meta_hpp
|
||||
template < class_kind Class >
|
||||
template < class_kind Base >
|
||||
class_bind<Class>& class_bind<Class>::base_() {
|
||||
static_assert(std::is_base_of_v<Base, Class>);
|
||||
auto base_data = detail::class_type_data::get<Base>();
|
||||
data_->bases.emplace(base_data);
|
||||
return *this;
|
||||
@@ -47,6 +49,7 @@ namespace meta_hpp
|
||||
template < class_kind Class >
|
||||
template < member_kind Member >
|
||||
class_bind<Class>& class_bind<Class>::member_(std::string name, Member member) {
|
||||
static_assert(std::same_as<Class, typename detail::member_traits<Member>::class_type>);
|
||||
auto member_state = detail::member_state::make<Member>(std::move(name), std::move(member));
|
||||
data_->members.emplace(member_state->index, std::move(member_state));
|
||||
return *this;
|
||||
@@ -55,6 +58,7 @@ namespace meta_hpp
|
||||
template < class_kind Class >
|
||||
template < method_kind Method >
|
||||
class_bind<Class>& class_bind<Class>::method_(std::string name, Method method) {
|
||||
static_assert(std::same_as<Class, typename detail::method_traits<Method>::class_type>);
|
||||
auto method_state = detail::method_state::make<Method>(std::move(name), std::move(method));
|
||||
data_->methods.emplace(method_state->index, std::move(method_state));
|
||||
return *this;
|
||||
|
||||
@@ -97,7 +97,21 @@ namespace meta_hpp
|
||||
}
|
||||
|
||||
inline bool class_type::is_base_of(const class_type& derived) const noexcept {
|
||||
return derived.data_ && derived.data_->bases.contains(*this);
|
||||
if ( !is_valid() || !derived.is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( derived.data_->bases.contains(*this) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for ( auto&& derived_base : derived.data_->bases ) {
|
||||
if ( is_base_of(derived_base) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template < class_kind Base >
|
||||
@@ -106,7 +120,21 @@ namespace meta_hpp
|
||||
}
|
||||
|
||||
inline bool class_type::is_derived_from(const class_type& base) const noexcept {
|
||||
return data_ && data_->bases.contains(base);
|
||||
if ( !is_valid() || !base.is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( data_->bases.contains(base) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for ( auto&& self_base : data_->bases ) {
|
||||
if ( self_base.is_derived_from(base) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline function class_type::get_function(std::string_view name) const noexcept {
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace
|
||||
|
||||
float base_clazz_2::base_variable_2 = 2.0f;
|
||||
|
||||
struct derived_clazz final : base_clazz_1, base_clazz_2 {
|
||||
struct derived_clazz : base_clazz_1, base_clazz_2 {
|
||||
derived_clazz(int i, float f)
|
||||
: base_clazz_1{i}
|
||||
, base_clazz_2{f} {}
|
||||
@@ -50,6 +50,10 @@ namespace
|
||||
static constexpr double derived_variable = 3.0;
|
||||
};
|
||||
|
||||
struct final_derived_clazz final : derived_clazz {
|
||||
using derived_clazz::derived_clazz;
|
||||
};
|
||||
|
||||
template < typename... Args >
|
||||
struct variadic_clazz {};
|
||||
}
|
||||
@@ -84,6 +88,10 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
.function_("derived_function", &derived_clazz::derived_function)
|
||||
.variable_("derived_variable", &derived_clazz::derived_variable);
|
||||
|
||||
meta::class_<final_derived_clazz>()
|
||||
.ctor_<int, float>()
|
||||
.base_<derived_clazz>();
|
||||
|
||||
const meta::class_type base_clazz_1_type = meta::resolve_type<base_clazz_1>();
|
||||
REQUIRE(base_clazz_1_type);
|
||||
|
||||
@@ -93,6 +101,9 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
const meta::class_type derived_clazz_type = meta::resolve_type<const derived_clazz>();
|
||||
REQUIRE(derived_clazz_type);
|
||||
|
||||
const meta::class_type final_derived_clazz_type = meta::resolve_type<const final_derived_clazz>();
|
||||
REQUIRE(final_derived_clazz_type);
|
||||
|
||||
const meta::class_type variadic_clazz_int_type = meta::resolve_type<variadic_clazz<int>>();
|
||||
REQUIRE(variadic_clazz_int_type);
|
||||
|
||||
@@ -102,7 +113,8 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
SUBCASE("get_flags") {
|
||||
CHECK(base_clazz_1_type.get_flags() == meta::class_flags{});
|
||||
CHECK(base_clazz_2_type.get_flags() == meta::class_flags{});
|
||||
CHECK(derived_clazz_type.get_flags() == meta::class_flags::is_final);
|
||||
CHECK(derived_clazz_type.get_flags() == meta::class_flags{});
|
||||
CHECK(final_derived_clazz_type.get_flags() == meta::class_flags::is_final);
|
||||
CHECK(variadic_clazz_int_type.get_flags() == (meta::class_flags::is_empty | meta::class_flags::is_template_instantiation));
|
||||
CHECK(variadic_clazz_int_float_type.get_flags() == (meta::class_flags::is_empty | meta::class_flags::is_template_instantiation));
|
||||
}
|
||||
@@ -111,6 +123,7 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
CHECK(base_clazz_1_type.get_size() == sizeof(base_clazz_1));
|
||||
CHECK(base_clazz_2_type.get_size() == sizeof(base_clazz_2));
|
||||
CHECK(derived_clazz_type.get_size() == sizeof(derived_clazz));
|
||||
CHECK(final_derived_clazz_type.get_size() == sizeof(final_derived_clazz));
|
||||
}
|
||||
|
||||
SUBCASE("get_arity") {
|
||||
@@ -174,36 +187,42 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
CHECK(base_clazz_1_type.get_ctors().size() == 1);
|
||||
CHECK(base_clazz_2_type.get_ctors().size() == 1);
|
||||
CHECK(derived_clazz_type.get_ctors().size() == 1);
|
||||
CHECK(final_derived_clazz_type.get_ctors().size() == 1);
|
||||
}
|
||||
|
||||
SUBCASE("get_bases") {
|
||||
CHECK(base_clazz_1_type.get_bases() == meta::class_set{});
|
||||
CHECK(base_clazz_2_type.get_bases() == meta::class_set{});
|
||||
CHECK(derived_clazz_type.get_bases() == meta::class_set{base_clazz_1_type, base_clazz_2_type});
|
||||
CHECK(final_derived_clazz_type.get_bases() == meta::class_set{derived_clazz_type});
|
||||
}
|
||||
|
||||
SUBCASE("get_functions") {
|
||||
CHECK(base_clazz_1_type.get_functions().size() == 3);
|
||||
CHECK(base_clazz_2_type.get_functions().size() == 1);
|
||||
CHECK(derived_clazz_type.get_functions().size() == 1);
|
||||
CHECK(final_derived_clazz_type.get_functions().size() == 0);
|
||||
}
|
||||
|
||||
SUBCASE("get_members") {
|
||||
CHECK(base_clazz_1_type.get_members().size() == 1);
|
||||
CHECK(base_clazz_2_type.get_members().size() == 1);
|
||||
CHECK(derived_clazz_type.get_members().size() == 1);
|
||||
CHECK(final_derived_clazz_type.get_members().size() == 0);
|
||||
}
|
||||
|
||||
SUBCASE("get_methods") {
|
||||
CHECK(base_clazz_1_type.get_methods().size() == 3);
|
||||
CHECK(base_clazz_2_type.get_methods().size() == 1);
|
||||
CHECK(derived_clazz_type.get_methods().size() == 1);
|
||||
CHECK(final_derived_clazz_type.get_methods().size() == 0);
|
||||
}
|
||||
|
||||
SUBCASE("get_variables") {
|
||||
CHECK(base_clazz_1_type.get_variables().size() == 1);
|
||||
CHECK(base_clazz_2_type.get_variables().size() == 1);
|
||||
CHECK(derived_clazz_type.get_variables().size() == 1);
|
||||
CHECK(final_derived_clazz_type.get_variables().size() == 0);
|
||||
}
|
||||
|
||||
SUBCASE("is_base_of") {
|
||||
@@ -216,6 +235,9 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
|
||||
CHECK(base_clazz_1_type.is_base_of<derived_clazz>());
|
||||
CHECK(base_clazz_1_type.is_base_of(derived_clazz_type));
|
||||
|
||||
CHECK(base_clazz_1_type.is_base_of<final_derived_clazz>());
|
||||
CHECK(base_clazz_1_type.is_base_of(final_derived_clazz_type));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -227,6 +249,9 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
|
||||
CHECK(base_clazz_2_type.is_base_of<derived_clazz>());
|
||||
CHECK(base_clazz_2_type.is_base_of(derived_clazz_type));
|
||||
|
||||
CHECK(base_clazz_2_type.is_base_of<final_derived_clazz>());
|
||||
CHECK(base_clazz_2_type.is_base_of(final_derived_clazz_type));
|
||||
}
|
||||
|
||||
{
|
||||
@@ -274,6 +299,17 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
CHECK_FALSE(derived_clazz_type.is_derived_from<derived_clazz>());
|
||||
CHECK_FALSE(derived_clazz_type.is_derived_from(derived_clazz_type));
|
||||
}
|
||||
|
||||
{
|
||||
CHECK(final_derived_clazz_type.is_derived_from<base_clazz_1>());
|
||||
CHECK(final_derived_clazz_type.is_derived_from(base_clazz_1_type));
|
||||
|
||||
CHECK(final_derived_clazz_type.is_derived_from<base_clazz_2>());
|
||||
CHECK(final_derived_clazz_type.is_derived_from(base_clazz_2_type));
|
||||
|
||||
CHECK(final_derived_clazz_type.is_derived_from<derived_clazz>());
|
||||
CHECK(final_derived_clazz_type.is_derived_from(derived_clazz_type));
|
||||
}
|
||||
}
|
||||
|
||||
SUBCASE("get_function") {
|
||||
|
||||
Reference in New Issue
Block a user