From ed37cfc394d576a04a384aea22c9ff80404b10aa Mon Sep 17 00:00:00 2001 From: Dan Dees Date: Mon, 20 May 2019 17:04:40 +0700 Subject: [PATCH] add get_direct_base_classes --- .../detail/registration/registration_impl.h | 2 +- src/rttr/detail/type/base_classes.h | 32 ++++++++++++------- src/rttr/detail/type/type_register.cpp | 6 ++-- src/rttr/type.cpp | 11 +++++++ src/rttr/type.h | 7 ++++ src/unit_tests/type/test_type.cpp | 11 +++++++ 6 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/rttr/detail/registration/registration_impl.h b/src/rttr/detail/registration/registration_impl.h index 96b96b5f..b1c83fb9 100644 --- a/src/rttr/detail/registration/registration_impl.h +++ b/src/rttr/detail/registration/registration_impl.h @@ -115,7 +115,7 @@ template registration::class_::~class_() { // make sure that all base classes are registered - detail::base_classes::get_types(); + detail::base_classes::get_types(true); } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/rttr/detail/type/base_classes.h b/src/rttr/detail/type/base_classes.h index aa47c680..53b66013 100644 --- a/src/rttr/detail/type/base_classes.h +++ b/src/rttr/detail/type/base_classes.h @@ -82,7 +82,7 @@ struct RTTR_LOCAL type_from_base_classes; template struct RTTR_LOCAL type_from_base_classes { - static RTTR_INLINE void fill(info_container&) + static RTTR_INLINE void fill(info_container&, bool) { } }; @@ -105,15 +105,25 @@ static void* rttr_cast_impl(void* ptr) template struct RTTR_LOCAL type_from_base_classes { - static RTTR_INLINE void fill(info_container& vec) + static RTTR_INLINE void fill(info_container& vec, bool do_all_bases) { static_assert(has_base_class_list::value, "The parent class has no base class list defined - please use the macro RTTR_ENABLE"); - vec.emplace_back(type::get(), &rttr_cast_impl); - // retrieve also the types of all base classes of the base classes; you will get an compile error here, - // when the base class has not defined the 'base_class_list' typedef - type_from_base_classes::fill(vec); - // continue with the rest - type_from_base_classes::fill(vec); + + // put away pair of "type" and cast to type + vec.emplace_back( + type::get(), + &rttr_cast_impl + ); + + if ( do_all_bases ) { + + // retrieve also the types of all base classes of the base classes; you will get an compile error here, + // when the base class has not defined the 'base_class_list' typedef + type_from_base_classes::fill(vec, do_all_bases); + } + + // continue with the rest of the bases in struct + type_from_base_classes::fill(vec, do_all_bases); } }; @@ -127,7 +137,7 @@ struct type_from_base_classes> : type_ template struct RTTR_LOCAL base_classes { - static RTTR_INLINE info_container get_types() + static RTTR_INLINE info_container get_types(bool) { info_container result; return result; @@ -137,10 +147,10 @@ struct RTTR_LOCAL base_classes template struct RTTR_LOCAL base_classes::value>::type> { - static RTTR_INLINE info_container get_types() + static RTTR_INLINE info_container get_types(bool do_all_bases) { info_container result; - type_from_base_classes::fill(result); + type_from_base_classes::fill(result, do_all_bases); return result; } }; diff --git a/src/rttr/detail/type/type_register.cpp b/src/rttr/detail/type/type_register.cpp index 25181117..ec18ebd4 100644 --- a/src/rttr/detail/type/type_register.cpp +++ b/src/rttr/detail/type/type_register.cpp @@ -505,7 +505,7 @@ type_data* type_register_private::register_name_if_neccessary(type_data* info) void type_register_private::register_base_class_info(type_data* info) { - auto base_classes = info->get_base_types(); + auto base_classes(info->get_base_types(true)); // remove double entries; can only be happen for virtual inheritance case set double_entries; @@ -529,9 +529,9 @@ void type_register_private::register_base_class_info(type_data* info) if (!base_classes.empty()) { - auto& class_data = info->m_class_data; for (const auto& t : base_classes) { + auto& class_data = info->m_class_data; class_data.m_base_types.push_back(t.m_base_type); class_data.m_conversion_list.push_back(t.m_rttr_cast_func); @@ -546,7 +546,7 @@ void type_register_private::register_base_class_info(type_data* info) type_data* type_register_private::register_type(type_data* info) RTTR_NOEXCEPT { // this will register the base types - info->get_base_types(); + info->get_base_types(true); using namespace detail; diff --git a/src/rttr/type.cpp b/src/rttr/type.cpp index 77aa4514..1627ffae 100644 --- a/src/rttr/type.cpp +++ b/src/rttr/type.cpp @@ -161,6 +161,17 @@ array_range type::get_base_classes() const RTTR_NOEXCEPT ///////////////////////////////////////////////////////////////////////////////////////// +std::vector type::get_direct_base_classes() const RTTR_NOEXCEPT +{ + std::vector db_vec; + for ( auto&& t : m_type_data->get_base_types(false) ) { + db_vec.emplace_back(t.m_base_type); // transform... + } + return db_vec; +} + +///////////////////////////////////////////////////////////////////////////////////////// + array_range type::get_derived_classes() const RTTR_NOEXCEPT { return array_range(m_type_data->m_class_data.m_derived_types.data(), diff --git a/src/rttr/type.h b/src/rttr/type.h index edced89a..fb14ab05 100644 --- a/src/rttr/type.h +++ b/src/rttr/type.h @@ -573,6 +573,13 @@ class RTTR_API type */ array_range get_base_classes() const RTTR_NOEXCEPT; + /*! + * \brief Returns a range of direct base classes of this type in order declarad in RTTR_ENABLE. + * + * \return A range of types. + */ + std::vector get_direct_base_classes() const RTTR_NOEXCEPT; + /*! * \brief Returns a range of all derived classes of this type. * diff --git a/src/unit_tests/type/test_type.cpp b/src/unit_tests/type/test_type.cpp index bdd77815..688632dc 100644 --- a/src/unit_tests/type/test_type.cpp +++ b/src/unit_tests/type/test_type.cpp @@ -287,6 +287,17 @@ TEST_CASE("type - get_base_classes()", "[type]") REQUIRE(base_list[2] == type::get()); } +TEST_CASE("type - get_direct_base_classes()", "[type]") +{ + DiamondBottom d; + const auto& base_list_range = type::get(d).get_direct_base_classes(); + REQUIRE(base_list_range.size() == 2); + + std::vector base_list(base_list_range.cbegin(), base_list_range.cend()); + REQUIRE(base_list[0] == type::get()); + REQUIRE(base_list[1] == type::get()); +} + ///////////////////////////////////////////////////////////////////////////////////////// TEST_CASE("type - is_base_of()", "[type]")