any/meta/poly: as_ref const and non-const overloads

This commit is contained in:
Michele Caini
2020-12-16 17:14:15 +01:00
parent c52f16f5b8
commit 6123e4ac8a
4 changed files with 40 additions and 17 deletions

3
TODO
View File

@@ -18,9 +18,8 @@
- ...
WIP:
* HP: any/meta_any/poly: ::REF -> ::CREF?
* HP: const poly storage function for the registry
* HP: meta, support for custom deref function other than operator*
* HP: meta, as_cref_t other than as_ref_t
* HP: headless (sparse set only) view
* HP: pass the registry to pools, basic poly storage should have only component member
* HP: make view pack work also with groups, make packs input iterator only, add view adapter for external sources

View File

@@ -16,7 +16,7 @@ namespace entt {
/*! @brief A SBO friendly, type-safe container for single values of any type. */
class any {
enum class operation { COPY, MOVE, DTOR, ADDR, CADDR, REF, TYPE };
enum class operation { COPY, MOVE, DTOR, ADDR, CADDR, REF, CREF, TYPE };
using storage_type = std::aligned_storage_t<sizeof(double[2]), alignof(double[2])>;
using vtable_type = const void *(const operation, const any &, const void *);
@@ -39,7 +39,8 @@ class any {
} else if constexpr(std::is_lvalue_reference_v<Type>) {
switch(op) {
case operation::REF:
as_any(to).vtable = from.vtable;
case operation::CREF:
as_any(to).vtable = (op == operation::REF) ? basic_vtable<Type &> : basic_vtable<const Type &>;
[[fallthrough]];
case operation::COPY:
case operation::MOVE:
@@ -72,7 +73,8 @@ class any {
case operation::CADDR:
return instance;
case operation::REF:
as_any(to).vtable = basic_vtable<Type &>;
case operation::CREF:
as_any(to).vtable = (op == operation::REF) ? basic_vtable<Type &> : basic_vtable<const Type &>;
as_any(to).instance = instance;
break;
case operation::TYPE:
@@ -84,6 +86,10 @@ class any {
case operation::COPY:
as_any(to).instance = new Type{*static_cast<const Type *>(from.instance)};
break;
case operation::REF:
case operation::CREF:
as_any(to).vtable = (op == operation::REF) ? basic_vtable<Type &> : basic_vtable<const Type &>;
[[fallthrough]];
case operation::MOVE:
as_any(to).instance = from.instance;
break;
@@ -93,10 +99,6 @@ class any {
case operation::ADDR:
case operation::CADDR:
return from.instance;
case operation::REF:
as_any(to).vtable = basic_vtable<Type &>;
as_any(to).instance = from.instance;
break;
case operation::TYPE:
as_type_info(to) = type_id<Type>();
break;
@@ -251,12 +253,19 @@ public:
* @param other A reference to an object that isn't necessarily initialized.
* @return An any that shares a reference to an unmanaged object.
*/
[[nodiscard]] friend any as_ref(const any &other) ENTT_NOEXCEPT {
[[nodiscard]] friend any as_ref(any &other) ENTT_NOEXCEPT {
any ref{};
other.vtable(operation::REF, other, &ref);
return ref;
}
/*! @copydoc as_ref */
[[nodiscard]] friend any as_ref(const any &other) ENTT_NOEXCEPT {
any ref{};
other.vtable(operation::CREF, other, &ref);
return ref;
}
private:
vtable_type *vtable;
union { const void *instance; storage_type storage; };

View File

@@ -221,7 +221,7 @@ public:
template<typename Type>
meta_any(std::reference_wrapper<Type> value)
: storage{value},
vtable{&basic_vtable<Type>},
vtable{&basic_vtable<std::remove_const_t<Type>>},
node{internal::meta_info<Type>::resolve()}
{}
@@ -500,6 +500,13 @@ public:
* @param other A reference to an object that isn't necessarily initialized.
* @return A meta any that shares a reference to an unmanaged object.
*/
[[nodiscard]] friend meta_any as_ref(meta_any &other) ENTT_NOEXCEPT {
meta_any ref = as_ref(std::as_const(other));
ref.storage = as_ref(other.storage);
return ref;
}
/*! @copydoc as_ref */
[[nodiscard]] friend meta_any as_ref(const meta_any &other) ENTT_NOEXCEPT {
meta_any ref{};
ref.node = other.node;
@@ -1655,9 +1662,9 @@ class meta_sequence_container::meta_iterator {
template<typename It>
[[nodiscard]] static meta_any deref(meta_any any) {
if constexpr(std::is_const_v<std::remove_reference_t<decltype(*std::declval<It>())>>) {
return *any.cast<It &>();
return *any.cast<const It &>();
} else {
return std::ref(*any.cast<It &>());
return std::ref(*any.cast<const It &>());
}
}
@@ -1901,9 +1908,9 @@ class meta_associative_container::meta_iterator {
template<bool KeyOnly, typename It>
[[nodiscard]] static meta_any key(meta_any any) {
if constexpr(KeyOnly) {
return *any.cast<It &>();
return *any.cast<const It &>();
} else {
return any.cast<It &>()->first;
return any.cast<const It &>()->first;
}
}
@@ -1912,7 +1919,7 @@ class meta_associative_container::meta_iterator {
if constexpr(KeyOnly) {
return meta_any{};
} else {
return std::ref(any.cast<It &>()->second);
return std::ref(any.cast<const It &>()->second);
}
}

View File

@@ -105,6 +105,7 @@ public:
*/
template<typename Type>
[[nodiscard]] static const auto * instance() {
static_assert(std::is_same_v<Type, std::decay_t<Type>>);
static const auto vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{});
return &vtable;
}
@@ -205,7 +206,7 @@ public:
template<typename Type>
poly(std::reference_wrapper<Type> value)
: storage{value},
vtable{poly_vtable<Concept>::template instance<Type>()}
vtable{poly_vtable<Concept>::template instance<std::remove_const_t<Type>>()}
{}
/**
@@ -314,6 +315,13 @@ public:
* @param other A reference to an object that isn't necessarily initialized.
* @return A poly that shares a reference to an unmanaged object.
*/
[[nodiscard]] friend poly as_ref(poly &other) ENTT_NOEXCEPT {
poly ref = as_ref(std::as_const(other));
ref.storage = as_ref(other.storage);
return ref;
}
/*! @copydoc as_ref */
[[nodiscard]] friend poly as_ref(const poly &other) ENTT_NOEXCEPT {
poly ref;
ref.storage = as_ref(other.storage);