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_data.h b/src/rttr/detail/type/type_data.h index 927f9c29..c183ab8d 100644 --- a/src/rttr/detail/type/type_data.h +++ b/src/rttr/detail/type/type_data.h @@ -77,6 +77,7 @@ struct RTTR_LOCAL class_data get_derived_info_func m_derived_info_func; std::vector m_base_types; + std::vector m_direct_base_types; std::vector m_derived_types; std::vector m_conversion_list; std::vector m_properties; diff --git a/src/rttr/detail/type/type_register.cpp b/src/rttr/detail/type/type_register.cpp index 25181117..52e6a31d 100644 --- a/src/rttr/detail/type/type_register.cpp +++ b/src/rttr/detail/type/type_register.cpp @@ -505,7 +505,8 @@ 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& class_data = info->m_class_data; + auto base_classes(info->get_base_types(true)); // remove double entries; can only be happen for virtual inheritance case set double_entries; @@ -529,7 +530,6 @@ 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) { class_data.m_base_types.push_back(t.m_base_type); @@ -539,6 +539,12 @@ void type_register_private::register_base_class_info(type_data* info) r_type.m_type_data->m_class_data.m_derived_types.push_back(type(info)); } } + + // base classes which directly inherit + for (const auto& t : info->get_base_types(false) ) + { + class_data.m_direct_base_types.emplace_back(t.m_base_type); + } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -546,7 +552,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..e8ac326e 100644 --- a/src/rttr/type.cpp +++ b/src/rttr/type.cpp @@ -161,6 +161,15 @@ array_range type::get_base_classes() const RTTR_NOEXCEPT ///////////////////////////////////////////////////////////////////////////////////////// +array_range type::get_direct_base_classes() const RTTR_NOEXCEPT +{ + return array_range( + m_type_data->m_class_data.m_direct_base_types.data(), + m_type_data->m_class_data.m_direct_base_types.size()); +} + +///////////////////////////////////////////////////////////////////////////////////////// + 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..47340899 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. + */ + array_range 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]")