any: plugin-friendly, faster quick check

This commit is contained in:
skypjack
2025-11-10 14:34:39 +01:00
parent 7111549c7c
commit fe8320c66f
2 changed files with 10 additions and 11 deletions

2
TODO
View File

@@ -32,8 +32,6 @@ TODO:
* paged vector as a standalone class
* resource: shared_from_this?
* finish the imgui viewer/editor!
* introduce compile-time flag to skip dll-only checks in basic_any
* archetype-like a-là EnTT support (see my own notes)
* meta_any refine allow_cast implementations
* meta: conversion_helper machinery has lot of room for improvements
* meta_factory: add a replace flag to traits to get around the |-only mechanism

View File

@@ -130,6 +130,7 @@ class basic_any: private internal::basic_any_storage<Len, Align> {
using plain_type = std::remove_const_t<std::remove_reference_t<Type>>;
vtable = basic_vtable<plain_type>;
underlying_type = type_hash<plain_type>::value();
if constexpr(std::is_void_v<Type>) {
deleter = nullptr;
@@ -243,6 +244,7 @@ public:
basic_any(basic_any &&other) noexcept
: base_type{},
vtable{other.vtable},
underlying_type{other.underlying_type},
deleter{other.deleter},
mode{other.mode} {
if(other.mode == any_policy::embedded) {
@@ -292,6 +294,7 @@ public:
}
vtable = other.vtable;
underlying_type = other.underlying_type;
deleter = other.deleter;
mode = other.mode;
}
@@ -327,7 +330,7 @@ public:
* otherwise.
*/
[[nodiscard]] bool has_value(const type_info &req) const noexcept {
return (info() == req);
return (underlying_type == req.hash());
}
/**
@@ -340,8 +343,7 @@ public:
template<typename Type>
[[nodiscard]] bool has_value() const noexcept {
static_assert(std::is_same_v<std::remove_const_t<Type>, Type>, "Invalid type");
// it could be a call across boundaries, but still for the same type
return (vtable == &basic_vtable<Type>) || has_value(type_id<Type>());
return (underlying_type == type_hash<Type>::value());
}
/**
@@ -437,8 +439,7 @@ public:
* @return True in case of success, false otherwise.
*/
bool assign(const basic_any &other) {
// it could be a call across boundaries, but still for the same type
if(other && (mode != any_policy::cref) && ((vtable == other.vtable) || has_value(other.info()))) {
if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
return (vtable(request::assign, *this, other.data()) != nullptr);
}
@@ -448,8 +449,7 @@ public:
/*! @copydoc assign */
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
bool assign(basic_any &&other) {
// it could be a call across boundaries, but still for the same type
if(other && (mode != any_policy::cref) && ((vtable == other.vtable) || has_value(other.info()))) {
if(other && (mode != any_policy::cref) && (underlying_type == other.underlying_type)) {
return (other.mode == any_policy::cref) ? (vtable(request::assign, *this, std::as_const(other).data()) != nullptr) : (vtable(request::transfer, *this, other.data()) != nullptr);
}
@@ -476,8 +476,7 @@ public:
* @return False if the two objects differ in their content, true otherwise.
*/
[[nodiscard]] bool operator==(const basic_any &other) const noexcept {
// it could be a call across boundaries, but still for the same type
if(other && ((vtable == other.vtable) || has_value(other.info()))) {
if(other && (underlying_type == other.underlying_type)) {
return (vtable(request::compare, *this, other.data()) != nullptr);
}
@@ -508,6 +507,7 @@ public:
basic_any other{};
other.instance = data();
other.vtable = vtable;
other.underlying_type = underlying_type;
other.mode = any_policy::cref;
return other;
}
@@ -531,6 +531,7 @@ public:
private:
vtable_type *vtable{};
deleter_type *deleter{};
id_type underlying_type{};
any_policy mode{};
};