meta: avoid a (maybe) UB in meta_any

This commit is contained in:
Michele Caini
2021-11-08 14:53:55 +01:00
parent 2cab2583c0
commit 5b3fd7537e

View File

@@ -155,7 +155,7 @@ class meta_any {
using vtable_type = void(const operation, const any &, void *);
template<typename Type>
static void basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const any &from, [[maybe_unused]] void *to) {
static void basic_vtable([[maybe_unused]] const operation op, [[maybe_unused]] const any &value, [[maybe_unused]] void *other) {
static_assert(std::is_same_v<std::remove_reference_t<std::remove_const_t<Type>>, Type>, "Invalid type");
if constexpr(!std::is_void_v<Type>) {
@@ -163,21 +163,21 @@ class meta_any {
case operation::deref:
if constexpr(is_meta_pointer_like_v<Type>) {
if constexpr(std::is_function_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
*static_cast<meta_any *>(to) = any_cast<Type>(from);
*static_cast<meta_any *>(other) = any_cast<Type>(value);
} else if constexpr(!std::is_same_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>, void>) {
using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(from)));
static_cast<meta_any *>(to)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(from)));
using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value)));
static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value)));
}
}
break;
case operation::seq:
if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) {
*static_cast<meta_sequence_container *>(to) = {std::in_place_type<Type>, std::move(const_cast<any &>(from))};
*static_cast<meta_sequence_container *>(other) = {std::in_place_type<Type>, std::move(const_cast<any &>(value))};
}
break;
case operation::assoc:
if constexpr(is_complete_v<meta_associative_container_traits<Type>>) {
*static_cast<meta_associative_container *>(to) = {std::in_place_type<Type>, std::move(const_cast<any &>(from))};
*static_cast<meta_associative_container *>(other) = {std::in_place_type<Type>, std::move(const_cast<any &>(value))};
}
break;
}
@@ -509,15 +509,17 @@ public:
* @return A sequence container proxy for the underlying object.
*/
[[nodiscard]] meta_sequence_container as_sequence_container() ENTT_NOEXCEPT {
any detached = storage.as_ref();
meta_sequence_container proxy;
vtable(operation::seq, storage.as_ref(), &proxy);
vtable(operation::seq, detached, &proxy);
return proxy;
}
/*! @copydoc as_sequence_container */
[[nodiscard]] meta_sequence_container as_sequence_container() const ENTT_NOEXCEPT {
any detached = storage.as_ref();
meta_sequence_container proxy;
vtable(operation::seq, storage.as_ref(), &proxy);
vtable(operation::seq, detached, &proxy);
return proxy;
}
@@ -526,15 +528,17 @@ public:
* @return An associative container proxy for the underlying object.
*/
[[nodiscard]] meta_associative_container as_associative_container() ENTT_NOEXCEPT {
any detached = storage.as_ref();
meta_associative_container proxy;
vtable(operation::assoc, storage.as_ref(), &proxy);
vtable(operation::assoc, detached, &proxy);
return proxy;
}
/*! @copydoc as_associative_container */
[[nodiscard]] meta_associative_container as_associative_container() const ENTT_NOEXCEPT {
any detached = storage.as_ref();
meta_associative_container proxy;
vtable(operation::assoc, storage.as_ref(), &proxy);
vtable(operation::assoc, detached, &proxy);
return proxy;
}
@@ -1463,13 +1467,13 @@ class meta_sequence_container::meta_iterator {
using vtable_type = void(const operation, const any &, void *);
template<typename It>
static void basic_vtable(const operation op, const any &from, void *to) {
static void basic_vtable(const operation op, const any &value, void *other) {
switch(op) {
case operation::incr:
++any_cast<It &>(const_cast<any &>(from));
++any_cast<It &>(const_cast<any &>(value));
break;
case operation::deref:
static_cast<meta_any *>(to)->emplace<typename std::iterator_traits<It>::reference>(*any_cast<const It &>(from));
static_cast<meta_any *>(other)->emplace<typename std::iterator_traits<It>::reference>(*any_cast<const It &>(value));
break;
}
}
@@ -1663,18 +1667,18 @@ class meta_associative_container::meta_iterator {
using vtable_type = void(const operation, const any &, void *);
template<bool KeyOnly, typename It>
static void basic_vtable(const operation op, const any &from, void *to) {
static void basic_vtable(const operation op, const any &value, void *other) {
switch(op) {
case operation::incr:
++any_cast<It &>(const_cast<any &>(from));
++any_cast<It &>(const_cast<any &>(value));
break;
case operation::deref:
const auto &it = any_cast<const It &>(from);
const auto &it = any_cast<const It &>(value);
if constexpr(KeyOnly) {
static_cast<std::pair<meta_any, meta_any> *>(to)->first.emplace<decltype(*it)>(*it);
static_cast<std::pair<meta_any, meta_any> *>(other)->first.emplace<decltype(*it)>(*it);
} else {
static_cast<std::pair<meta_any, meta_any> *>(to)->first.emplace<decltype((it->first))>(it->first);
static_cast<std::pair<meta_any, meta_any> *>(to)->second.emplace<decltype((it->second))>(it->second);
static_cast<std::pair<meta_any, meta_any> *>(other)->first.emplace<decltype((it->first))>(it->first);
static_cast<std::pair<meta_any, meta_any> *>(other)->second.emplace<decltype((it->second))>(it->second);
}
break;
}