any_cast: review any_cast for better support to const references

This commit is contained in:
Michele Caini
2020-12-15 15:56:01 +01:00
parent 1075ded4dc
commit bc089bc4c1
2 changed files with 41 additions and 13 deletions

View File

@@ -270,7 +270,7 @@ private:
*/
template<typename Type>
Type any_cast(const any &data) ENTT_NOEXCEPT {
auto * const instance = any_cast<std::remove_cv_t<std::remove_reference_t<Type>>>(&data);
auto * const instance = any_cast<std::remove_reference_t<Type>>(&data);
ENTT_ASSERT(instance);
return static_cast<Type>(*instance);
}
@@ -279,23 +279,16 @@ Type any_cast(const any &data) ENTT_NOEXCEPT {
/*! @copydoc any_cast */
template<typename Type>
Type any_cast(any &data) ENTT_NOEXCEPT {
if constexpr(!std::is_reference_v<Type> || std::is_const_v<std::remove_reference_t<Type>>) {
// last attempt to make wrappers for const references return their values
auto * const instance = any_cast<std::remove_cv_t<std::remove_reference_t<Type>>>(&std::as_const(data));
ENTT_ASSERT(instance);
return static_cast<Type>(*instance);
} else {
auto * const instance = any_cast<std::remove_cv_t<std::remove_reference_t<Type>>>(&data);
ENTT_ASSERT(instance);
return static_cast<Type>(*instance);
}
auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
ENTT_ASSERT(instance);
return static_cast<Type>(*instance);
}
/*! @copydoc any_cast */
template<typename Type>
Type any_cast(any &&data) ENTT_NOEXCEPT {
auto * const instance = any_cast<std::remove_cv_t<std::remove_reference_t<Type>>>(&data);
auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
ENTT_ASSERT(instance);
return static_cast<Type>(std::move(*instance));
}
@@ -311,7 +304,12 @@ const Type * any_cast(const any *data) ENTT_NOEXCEPT {
/*! @copydoc any_cast */
template<typename Type>
Type * any_cast(any *data) ENTT_NOEXCEPT {
return (data->type() == type_id<Type>() ? static_cast<Type *>(data->data()) : nullptr);
if constexpr(std::is_const_v<Type>) {
// last attempt to make wrappers for const references return their values
return any_cast<std::remove_const_t<Type>>(&std::as_const(*data));
} else {
return (data->type() == type_id<Type>() ? static_cast<Type *>(data->data()) : nullptr);
}
}

View File

@@ -68,9 +68,18 @@ TEST(Any, SBOAsRefConstruction) {
ASSERT_TRUE(any);
ASSERT_EQ(any.type(), entt::type_id<int>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<const int>(&any), &value);
ASSERT_EQ(entt::any_cast<int>(&any), &value);
ASSERT_EQ(entt::any_cast<const int>(&std::as_const(any)), &value);
ASSERT_EQ(entt::any_cast<int>(&std::as_const(any)), &value);
ASSERT_EQ(entt::any_cast<const int &>(any), 42);
ASSERT_EQ(entt::any_cast<int>(any), 42);
ASSERT_EQ(any.data(), &value);
ASSERT_EQ(std::as_const(any).data(), &value);
auto other = as_ref(any);
@@ -86,10 +95,16 @@ TEST(Any, SBOAsConstRefConstruction) {
ASSERT_TRUE(any);
ASSERT_EQ(any.type(), entt::type_id<int>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<const int>(&any), &value);
ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
ASSERT_EQ(entt::any_cast<const int>(&std::as_const(any)), &value);
ASSERT_EQ(entt::any_cast<int>(&std::as_const(any)), &value);
ASSERT_EQ(entt::any_cast<const int &>(any), 42);
ASSERT_EQ(entt::any_cast<int>(any), 42);
ASSERT_EQ(any.data(), nullptr);
ASSERT_EQ(std::as_const(any).data(), &value);
@@ -186,9 +201,18 @@ TEST(Any, NoSBOAsRefConstruction) {
ASSERT_TRUE(any);
ASSERT_EQ(any.type(), entt::type_id<fat>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<const fat>(&any), &instance);
ASSERT_EQ(entt::any_cast<fat>(&any), &instance);
ASSERT_EQ(entt::any_cast<const fat>(&std::as_const(any)), &instance);
ASSERT_EQ(entt::any_cast<fat>(&std::as_const(any)), &instance);
ASSERT_EQ(entt::any_cast<const fat &>(any), instance);
ASSERT_EQ(entt::any_cast<fat>(any), instance);
ASSERT_EQ(any.data(), &instance);
ASSERT_EQ(std::as_const(any).data(), &instance);
auto other = as_ref(any);
@@ -204,10 +228,16 @@ TEST(Any, NoSBOAsConstRefConstruction) {
ASSERT_TRUE(any);
ASSERT_EQ(any.type(), entt::type_id<fat>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<const fat>(&any), &instance);
ASSERT_EQ(entt::any_cast<fat>(&any), nullptr);
ASSERT_EQ(entt::any_cast<const fat>(&std::as_const(any)), &instance);
ASSERT_EQ(entt::any_cast<fat>(&std::as_const(any)), &instance);
ASSERT_EQ(entt::any_cast<const fat &>(any), instance);
ASSERT_EQ(entt::any_cast<fat>(any), instance);
ASSERT_EQ(any.data(), nullptr);
ASSERT_EQ(std::as_const(any).data(), &instance);