mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-13 11:17:06 +07:00
remove rtti types from type registry
This commit is contained in:
@@ -30,8 +30,6 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <typeindex>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <version>
|
#include <version>
|
||||||
@@ -4152,76 +4150,6 @@ namespace meta_hpp::detail
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
|
||||||
{
|
|
||||||
class state_registry final {
|
|
||||||
public:
|
|
||||||
class locker final {
|
|
||||||
public:
|
|
||||||
explicit locker()
|
|
||||||
: lock_{instance().mutex_} {}
|
|
||||||
|
|
||||||
~locker() = default;
|
|
||||||
|
|
||||||
locker(locker&&) = default;
|
|
||||||
locker& operator=(locker&&) = default;
|
|
||||||
|
|
||||||
locker(const locker&) = delete;
|
|
||||||
locker& operator=(const locker&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_lock<std::recursive_mutex> lock_;
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] static state_registry& instance() {
|
|
||||||
static state_registry instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
template < typename F >
|
|
||||||
void for_each_scope(F&& f) const {
|
|
||||||
const locker lock;
|
|
||||||
|
|
||||||
for ( auto&& [name, scope] : scopes_ ) {
|
|
||||||
std::invoke(f, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] scope get_scope_by_name(std::string_view name) const noexcept {
|
|
||||||
const locker lock;
|
|
||||||
|
|
||||||
if ( auto iter{scopes_.find(name)}; iter != scopes_.end() ) {
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return scope{};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] scope resolve_scope(std::string_view name) {
|
|
||||||
const locker lock;
|
|
||||||
|
|
||||||
if ( auto iter{scopes_.find(name)}; iter != scopes_.end() ) {
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto&& [iter, _] = scopes_.emplace( //
|
|
||||||
std::string{name},
|
|
||||||
scope_state::make(std::string{name}, metadata_map{})
|
|
||||||
);
|
|
||||||
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
state_registry() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::recursive_mutex mutex_;
|
|
||||||
std::map<std::string, scope, std::less<>> scopes_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
class type_registry final {
|
class type_registry final {
|
||||||
@@ -4268,18 +4196,6 @@ namespace meta_hpp::detail
|
|||||||
return any_type{};
|
return any_type{};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
|
||||||
[[nodiscard]] any_type get_type_by_rtti(const std::type_index& index) const noexcept {
|
|
||||||
const locker lock;
|
|
||||||
|
|
||||||
if ( auto iter{rtti_types_.find(index)}; iter != rtti_types_.end() ) {
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return any_type{};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template < array_kind Array >
|
template < array_kind Array >
|
||||||
[[nodiscard]] array_type resolve_type() {
|
[[nodiscard]] array_type resolve_type() {
|
||||||
@@ -4487,29 +4403,106 @@ namespace meta_hpp::detail
|
|||||||
template < typename Type, typename TypeData >
|
template < typename Type, typename TypeData >
|
||||||
void ensure_type(TypeData& type_data) {
|
void ensure_type(TypeData& type_data) {
|
||||||
const locker lock;
|
const locker lock;
|
||||||
|
types_.emplace(any_type{&type_data});
|
||||||
auto&& [position, emplaced] = types_.emplace(any_type{&type_data});
|
|
||||||
if ( !emplaced ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
|
||||||
META_HPP_TRY {
|
|
||||||
rtti_types_.emplace(typeid(Type), any_type{&type_data});
|
|
||||||
}
|
|
||||||
META_HPP_CATCH(...) {
|
|
||||||
types_.erase(position);
|
|
||||||
META_HPP_RETHROW();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::recursive_mutex mutex_;
|
std::recursive_mutex mutex_;
|
||||||
std::set<any_type, std::less<>> types_;
|
std::set<any_type, std::less<>> types_;
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
};
|
||||||
std::map<std::type_index, any_type, std::less<>> rtti_types_;
|
}
|
||||||
#endif
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
struct poly_info final {
|
||||||
|
const void* ptr{};
|
||||||
|
class_type type{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept check_poly_info_enabled //
|
||||||
|
= requires(type_registry& r, const T& v) {
|
||||||
|
{ v.get_most_derived_poly_info(r) } -> std::convertible_to<poly_info>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#define META_HPP_ENABLE_POLY_INFO() \
|
||||||
|
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 { \
|
||||||
|
using self_type = std::remove_cvref_t<decltype(*this)>; \
|
||||||
|
return ::meta_hpp::detail::poly_info{.ptr = this, .type = registry.resolve_class_type<self_type>()}; \
|
||||||
|
} \
|
||||||
|
META_HPP_IGNORE_OVERRIDE_WARNINGS_POP() \
|
||||||
|
private:
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
class state_registry final {
|
||||||
|
public:
|
||||||
|
class locker final {
|
||||||
|
public:
|
||||||
|
explicit locker()
|
||||||
|
: lock_{instance().mutex_} {}
|
||||||
|
|
||||||
|
~locker() = default;
|
||||||
|
|
||||||
|
locker(locker&&) = default;
|
||||||
|
locker& operator=(locker&&) = default;
|
||||||
|
|
||||||
|
locker(const locker&) = delete;
|
||||||
|
locker& operator=(const locker&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_lock<std::recursive_mutex> lock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] static state_registry& instance() {
|
||||||
|
static state_registry instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template < typename F >
|
||||||
|
void for_each_scope(F&& f) const {
|
||||||
|
const locker lock;
|
||||||
|
|
||||||
|
for ( auto&& [name, scope] : scopes_ ) {
|
||||||
|
std::invoke(f, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] scope get_scope_by_name(std::string_view name) const noexcept {
|
||||||
|
const locker lock;
|
||||||
|
|
||||||
|
if ( auto iter{scopes_.find(name)}; iter != scopes_.end() ) {
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scope{};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] scope resolve_scope(std::string_view name) {
|
||||||
|
const locker lock;
|
||||||
|
|
||||||
|
if ( auto iter{scopes_.find(name)}; iter != scopes_.end() ) {
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto&& [iter, _] = scopes_.emplace( //
|
||||||
|
std::string{name},
|
||||||
|
scope_state::make(std::string{name}, metadata_map{})
|
||||||
|
);
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
state_registry() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::recursive_mutex mutex_;
|
||||||
|
std::map<std::string, scope, std::less<>> scopes_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4567,16 +4560,19 @@ namespace meta_hpp
|
|||||||
return registry.resolve_destructor_type<Class>();
|
return registry.resolve_destructor_type<Class>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename From >
|
||||||
[[nodiscard]] any_type resolve_polymorphic_type(T&& v) noexcept {
|
requires std::is_class_v<std::remove_reference_t<From>>
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
[[nodiscard]] class_type resolve_poly_type(From&& from) noexcept {
|
||||||
|
using from_data_type = std::remove_reference_t<From>;
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
detail::check_poly_info_enabled<from_data_type>,
|
||||||
|
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it."
|
||||||
|
);
|
||||||
|
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
type_registry& registry = type_registry::instance();
|
type_registry& registry = type_registry::instance();
|
||||||
return registry.get_type_by_rtti(typeid(v));
|
return from.get_most_derived_poly_info(registry).type;
|
||||||
#else
|
|
||||||
(void)v;
|
|
||||||
return any_type{};
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9133,20 +9129,6 @@ namespace meta_hpp
|
|||||||
To ucast(From&& from);
|
To ucast(From&& from);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
|
||||||
{
|
|
||||||
struct polymorphic_meta_info {
|
|
||||||
const void* ptr{};
|
|
||||||
class_type type{};
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
concept check_polymorphic_cast_support //
|
|
||||||
= requires(type_registry& r, const T& v) {
|
|
||||||
{ v.get_most_derived_polymorphic_meta_info(r) } -> std::convertible_to<polymorphic_meta_info>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp
|
namespace meta_hpp
|
||||||
{
|
{
|
||||||
template < typename To, typename From >
|
template < typename To, typename From >
|
||||||
@@ -9156,8 +9138,8 @@ namespace meta_hpp
|
|||||||
using to_data_type = std::remove_pointer_t<To>;
|
using to_data_type = std::remove_pointer_t<To>;
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::check_polymorphic_cast_support<from_data_type>,
|
detail::check_poly_info_enabled<from_data_type>,
|
||||||
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLYMORPHIC_CAST macro to fix it."
|
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it."
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( from == nullptr ) {
|
if ( from == nullptr ) {
|
||||||
@@ -9168,12 +9150,12 @@ namespace meta_hpp
|
|||||||
return from;
|
return from;
|
||||||
} else {
|
} else {
|
||||||
detail::type_registry& registry{detail::type_registry::instance()};
|
detail::type_registry& registry{detail::type_registry::instance()};
|
||||||
const detail::polymorphic_meta_info& meta_info{from->get_most_derived_polymorphic_meta_info(registry)};
|
const detail::poly_info& meta_info{from->get_most_derived_poly_info(registry)};
|
||||||
|
|
||||||
// NOLINTNEXTLINE(*-const-cast)
|
// NOLINTNEXTLINE(*-const-cast)
|
||||||
void* most_derived_object_ptr = const_cast<void*>(meta_info.ptr);
|
void* most_derived_object_ptr = const_cast<void*>(meta_info.ptr);
|
||||||
|
|
||||||
if constexpr ( std::is_void_v<std::remove_cv_t<to_data_type>> ) {
|
if constexpr ( std::is_void_v<to_data_type> ) {
|
||||||
return most_derived_object_ptr;
|
return most_derived_object_ptr;
|
||||||
} else {
|
} else {
|
||||||
const class_type& to_class_type = registry.resolve_class_type<to_data_type>();
|
const class_type& to_class_type = registry.resolve_class_type<to_data_type>();
|
||||||
@@ -9189,8 +9171,8 @@ namespace meta_hpp
|
|||||||
using to_data_type = std::remove_reference_t<To>;
|
using to_data_type = std::remove_reference_t<To>;
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::check_polymorphic_cast_support<from_data_type>,
|
detail::check_poly_info_enabled<from_data_type>,
|
||||||
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLYMORPHIC_CAST macro to fix it."
|
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it."
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( to_data_type* ptr = ucast<to_data_type*>(std::addressof(from)) ) {
|
if ( to_data_type* ptr = ucast<to_data_type*>(std::addressof(from)) ) {
|
||||||
@@ -9201,18 +9183,6 @@ namespace meta_hpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define META_HPP_ENABLE_POLYMORPHIC_CAST() \
|
|
||||||
public: \
|
|
||||||
META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \
|
|
||||||
virtual ::meta_hpp::detail::polymorphic_meta_info get_most_derived_polymorphic_meta_info( \
|
|
||||||
::meta_hpp::detail::type_registry& registry \
|
|
||||||
) const { \
|
|
||||||
using self_type = std::remove_cvref_t<decltype(*this)>; \
|
|
||||||
return ::meta_hpp::detail::polymorphic_meta_info{.ptr = this, .type = registry.resolve_class_type<self_type>()}; \
|
|
||||||
} \
|
|
||||||
META_HPP_IGNORE_OVERRIDE_WARNINGS_POP() \
|
|
||||||
private:
|
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
namespace meta_hpp::detail
|
||||||
{
|
{
|
||||||
template < typename T >
|
template < typename T >
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ namespace
|
|||||||
A& operator=(const A&) = delete;
|
A& operator=(const A&) = delete;
|
||||||
|
|
||||||
virtual ~A() = default;
|
virtual ~A() = default;
|
||||||
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
struct B : virtual A {};
|
struct B : virtual A { META_HPP_ENABLE_POLY_INFO() };
|
||||||
struct C : virtual A {};
|
struct C : virtual A { META_HPP_ENABLE_POLY_INFO() };
|
||||||
struct D : B, C {};
|
struct D : B, C { META_HPP_ENABLE_POLY_INFO() };
|
||||||
struct E {};
|
struct E {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,24 +323,42 @@ TEST_CASE("meta/meta_features/diamond") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBCASE("resolve_polymorphic_type") {
|
SUBCASE("resolve_poly_type") {
|
||||||
const D d;
|
D d;
|
||||||
|
|
||||||
const A& ad = d;
|
A& ad = d;
|
||||||
const B& bd = d;
|
B& bd = d;
|
||||||
const C& cd = d;
|
C& cd = d;
|
||||||
const D& dd = d;
|
D& dd = d;
|
||||||
|
|
||||||
CHECK(meta::resolve_type(ad) == meta::resolve_type<A>());
|
CHECK(meta::resolve_type(ad) == meta::resolve_type<A>());
|
||||||
CHECK(meta::resolve_type(bd) == meta::resolve_type<B>());
|
CHECK(meta::resolve_type(bd) == meta::resolve_type<B>());
|
||||||
CHECK(meta::resolve_type(cd) == meta::resolve_type<C>());
|
CHECK(meta::resolve_type(cd) == meta::resolve_type<C>());
|
||||||
CHECK(meta::resolve_type(dd) == meta::resolve_type<D>());
|
CHECK(meta::resolve_type(dd) == meta::resolve_type<D>());
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
CHECK(meta::resolve_type(std::as_const(ad)) == meta::resolve_type<A>());
|
||||||
CHECK(meta::resolve_polymorphic_type(ad) == meta::resolve_type<D>());
|
CHECK(meta::resolve_type(std::as_const(bd)) == meta::resolve_type<B>());
|
||||||
CHECK(meta::resolve_polymorphic_type(bd) == meta::resolve_type<D>());
|
CHECK(meta::resolve_type(std::as_const(cd)) == meta::resolve_type<C>());
|
||||||
CHECK(meta::resolve_polymorphic_type(cd) == meta::resolve_type<D>());
|
CHECK(meta::resolve_type(std::as_const(dd)) == meta::resolve_type<D>());
|
||||||
CHECK(meta::resolve_polymorphic_type(dd) == meta::resolve_type<D>());
|
|
||||||
#endif
|
CHECK(meta::resolve_poly_type(A{}) == meta::resolve_type<A>());
|
||||||
|
CHECK(meta::resolve_poly_type(B{}) == meta::resolve_type<B>());
|
||||||
|
CHECK(meta::resolve_poly_type(C{}) == meta::resolve_type<C>());
|
||||||
|
CHECK(meta::resolve_poly_type(D{}) == meta::resolve_type<D>());
|
||||||
|
|
||||||
|
CHECK(meta::resolve_poly_type(ad) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(bd) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(cd) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(dd) == meta::resolve_type<D>());
|
||||||
|
|
||||||
|
CHECK(meta::resolve_poly_type(std::move(ad)) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(std::move(bd)) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(std::move(cd)) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(std::move(dd)) == meta::resolve_type<D>());
|
||||||
|
|
||||||
|
CHECK(meta::resolve_poly_type(std::as_const(ad)) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(std::as_const(bd)) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(std::as_const(cd)) == meta::resolve_type<D>());
|
||||||
|
CHECK(meta::resolve_poly_type(std::as_const(dd)) == meta::resolve_type<D>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,21 +14,21 @@ namespace
|
|||||||
A1(const A1&) = default;
|
A1(const A1&) = default;
|
||||||
virtual ~A1() = default;
|
virtual ~A1() = default;
|
||||||
char a{'a'};
|
char a{'a'};
|
||||||
META_HPP_ENABLE_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
struct B1 : A1 {
|
struct B1 : A1 {
|
||||||
B1() = default;
|
B1() = default;
|
||||||
B1(const B1&) = default;
|
B1(const B1&) = default;
|
||||||
char b{'b'};
|
char b{'b'};
|
||||||
META_HPP_ENABLE_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
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_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
// A1 <- B1 <- C1
|
// A1 <- B1 <- C1
|
||||||
@@ -38,21 +38,21 @@ namespace
|
|||||||
A2(const A2&) = default;
|
A2(const A2&) = default;
|
||||||
virtual ~A2() = default;
|
virtual ~A2() = default;
|
||||||
char a{'a'};
|
char a{'a'};
|
||||||
META_HPP_ENABLE_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
struct B2 : virtual A2 {
|
struct B2 : virtual A2 {
|
||||||
B2() = default;
|
B2() = default;
|
||||||
B2(const B2&) = default;
|
B2(const B2&) = default;
|
||||||
char b{'b'};
|
char b{'b'};
|
||||||
META_HPP_ENABLE_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
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_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -61,21 +61,21 @@ namespace
|
|||||||
D2(const D2&) = default;
|
D2(const D2&) = default;
|
||||||
virtual ~D2() = default;
|
virtual ~D2() = default;
|
||||||
char d{'d'};
|
char d{'d'};
|
||||||
META_HPP_ENABLE_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
struct E2 : D2 {
|
struct E2 : D2 {
|
||||||
E2() = default;
|
E2() = default;
|
||||||
E2(const E2&) = default;
|
E2(const E2&) = default;
|
||||||
char e{'e'};
|
char e{'e'};
|
||||||
META_HPP_ENABLE_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
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_POLYMORPHIC_CAST()
|
META_HPP_ENABLE_POLY_INFO()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,6 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <typeindex>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <version>
|
#include <version>
|
||||||
|
|||||||
36
headers/meta.hpp/meta_detail/poly_info.hpp
Normal file
36
headers/meta.hpp/meta_detail/poly_info.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../meta_base.hpp"
|
||||||
|
#include "../meta_types.hpp"
|
||||||
|
|
||||||
|
#include "type_registry.hpp"
|
||||||
|
|
||||||
|
namespace meta_hpp::detail
|
||||||
|
{
|
||||||
|
struct poly_info final {
|
||||||
|
const void* ptr{};
|
||||||
|
class_type type{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
concept check_poly_info_enabled //
|
||||||
|
= requires(type_registry& r, const T& v) {
|
||||||
|
{ v.get_most_derived_poly_info(r) } -> std::convertible_to<poly_info>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#define META_HPP_ENABLE_POLY_INFO() \
|
||||||
|
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 { \
|
||||||
|
using self_type = std::remove_cvref_t<decltype(*this)>; \
|
||||||
|
return ::meta_hpp::detail::poly_info{.ptr = this, .type = registry.resolve_class_type<self_type>()}; \
|
||||||
|
} \
|
||||||
|
META_HPP_IGNORE_OVERRIDE_WARNINGS_POP() \
|
||||||
|
private:
|
||||||
@@ -55,18 +55,6 @@ namespace meta_hpp::detail
|
|||||||
return any_type{};
|
return any_type{};
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
|
||||||
[[nodiscard]] any_type get_type_by_rtti(const std::type_index& index) const noexcept {
|
|
||||||
const locker lock;
|
|
||||||
|
|
||||||
if ( auto iter{rtti_types_.find(index)}; iter != rtti_types_.end() ) {
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return any_type{};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template < array_kind Array >
|
template < array_kind Array >
|
||||||
[[nodiscard]] array_type resolve_type() {
|
[[nodiscard]] array_type resolve_type() {
|
||||||
@@ -274,28 +262,11 @@ namespace meta_hpp::detail
|
|||||||
template < typename Type, typename TypeData >
|
template < typename Type, typename TypeData >
|
||||||
void ensure_type(TypeData& type_data) {
|
void ensure_type(TypeData& type_data) {
|
||||||
const locker lock;
|
const locker lock;
|
||||||
|
types_.emplace(any_type{&type_data});
|
||||||
auto&& [position, emplaced] = types_.emplace(any_type{&type_data});
|
|
||||||
if ( !emplaced ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
|
||||||
META_HPP_TRY {
|
|
||||||
rtti_types_.emplace(typeid(Type), any_type{&type_data});
|
|
||||||
}
|
|
||||||
META_HPP_CATCH(...) {
|
|
||||||
types_.erase(position);
|
|
||||||
META_HPP_RETHROW();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::recursive_mutex mutex_;
|
std::recursive_mutex mutex_;
|
||||||
std::set<any_type, std::less<>> types_;
|
std::set<any_type, std::less<>> types_;
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
|
||||||
std::map<std::type_index, any_type, std::less<>> rtti_types_;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +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/state_registry.hpp"
|
#include "meta_detail/state_registry.hpp"
|
||||||
#include "meta_detail/type_registry.hpp"
|
#include "meta_detail/type_registry.hpp"
|
||||||
|
|
||||||
@@ -67,16 +68,19 @@ namespace meta_hpp
|
|||||||
return registry.resolve_destructor_type<Class>();
|
return registry.resolve_destructor_type<Class>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename From >
|
||||||
[[nodiscard]] any_type resolve_polymorphic_type(T&& v) noexcept {
|
requires std::is_class_v<std::remove_reference_t<From>>
|
||||||
#if !defined(META_HPP_NO_RTTI)
|
[[nodiscard]] class_type resolve_poly_type(From&& from) noexcept {
|
||||||
|
using from_data_type = std::remove_reference_t<From>;
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
detail::check_poly_info_enabled<from_data_type>,
|
||||||
|
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it."
|
||||||
|
);
|
||||||
|
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
type_registry& registry = type_registry::instance();
|
type_registry& registry = type_registry::instance();
|
||||||
return registry.get_type_by_rtti(typeid(v));
|
return from.get_most_derived_poly_info(registry).type;
|
||||||
#else
|
|
||||||
(void)v;
|
|
||||||
return any_type{};
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,23 +9,10 @@
|
|||||||
#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/type_registry.hpp"
|
#include "../meta_detail/type_registry.hpp"
|
||||||
#include "../meta_detail/value_utilities/utraits.hpp"
|
#include "../meta_detail/value_utilities/utraits.hpp"
|
||||||
|
|
||||||
namespace meta_hpp::detail
|
|
||||||
{
|
|
||||||
struct polymorphic_meta_info {
|
|
||||||
const void* ptr{};
|
|
||||||
class_type type{};
|
|
||||||
};
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
concept check_polymorphic_cast_support //
|
|
||||||
= requires(type_registry& r, const T& v) {
|
|
||||||
{ v.get_most_derived_polymorphic_meta_info(r) } -> std::convertible_to<polymorphic_meta_info>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace meta_hpp
|
namespace meta_hpp
|
||||||
{
|
{
|
||||||
template < typename To, typename From >
|
template < typename To, typename From >
|
||||||
@@ -35,8 +22,8 @@ namespace meta_hpp
|
|||||||
using to_data_type = std::remove_pointer_t<To>;
|
using to_data_type = std::remove_pointer_t<To>;
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::check_polymorphic_cast_support<from_data_type>,
|
detail::check_poly_info_enabled<from_data_type>,
|
||||||
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLYMORPHIC_CAST macro to fix it."
|
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it."
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( from == nullptr ) {
|
if ( from == nullptr ) {
|
||||||
@@ -47,12 +34,12 @@ namespace meta_hpp
|
|||||||
return from;
|
return from;
|
||||||
} else {
|
} else {
|
||||||
detail::type_registry& registry{detail::type_registry::instance()};
|
detail::type_registry& registry{detail::type_registry::instance()};
|
||||||
const detail::polymorphic_meta_info& meta_info{from->get_most_derived_polymorphic_meta_info(registry)};
|
const detail::poly_info& meta_info{from->get_most_derived_poly_info(registry)};
|
||||||
|
|
||||||
// NOLINTNEXTLINE(*-const-cast)
|
// NOLINTNEXTLINE(*-const-cast)
|
||||||
void* most_derived_object_ptr = const_cast<void*>(meta_info.ptr);
|
void* most_derived_object_ptr = const_cast<void*>(meta_info.ptr);
|
||||||
|
|
||||||
if constexpr ( std::is_void_v<std::remove_cv_t<to_data_type>> ) {
|
if constexpr ( std::is_void_v<to_data_type> ) {
|
||||||
return most_derived_object_ptr;
|
return most_derived_object_ptr;
|
||||||
} else {
|
} else {
|
||||||
const class_type& to_class_type = registry.resolve_class_type<to_data_type>();
|
const class_type& to_class_type = registry.resolve_class_type<to_data_type>();
|
||||||
@@ -68,8 +55,8 @@ namespace meta_hpp
|
|||||||
using to_data_type = std::remove_reference_t<To>;
|
using to_data_type = std::remove_reference_t<To>;
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
detail::check_polymorphic_cast_support<from_data_type>,
|
detail::check_poly_info_enabled<from_data_type>,
|
||||||
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLYMORPHIC_CAST macro to fix it."
|
"The type doesn't support ucasts. Use the META_HPP_ENABLE_POLY_INFO macro to fix it."
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( to_data_type* ptr = ucast<to_data_type*>(std::addressof(from)) ) {
|
if ( to_data_type* ptr = ucast<to_data_type*>(std::addressof(from)) ) {
|
||||||
@@ -79,15 +66,3 @@ namespace meta_hpp
|
|||||||
throw_exception(error_code::bad_cast);
|
throw_exception(error_code::bad_cast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define META_HPP_ENABLE_POLYMORPHIC_CAST() \
|
|
||||||
public: \
|
|
||||||
META_HPP_IGNORE_OVERRIDE_WARNINGS_PUSH() \
|
|
||||||
virtual ::meta_hpp::detail::polymorphic_meta_info get_most_derived_polymorphic_meta_info( \
|
|
||||||
::meta_hpp::detail::type_registry& registry \
|
|
||||||
) const { \
|
|
||||||
using self_type = std::remove_cvref_t<decltype(*this)>; \
|
|
||||||
return ::meta_hpp::detail::polymorphic_meta_info{.ptr = this, .type = registry.resolve_class_type<self_type>()}; \
|
|
||||||
} \
|
|
||||||
META_HPP_IGNORE_OVERRIDE_WARNINGS_POP() \
|
|
||||||
private:
|
|
||||||
|
|||||||
Reference in New Issue
Block a user