Kaynağa Gözat

any_cast: review any_cast for better support to const references

Michele Caini 5 yıl önce
ebeveyn
işleme
bc089bc4c1
2 değiştirilmiş dosya ile 41 ekleme ve 13 silme
  1. 11 13
      src/entt/core/any.hpp
  2. 30 0
      test/entt/core/any.cpp

+ 11 - 13
src/entt/core/any.hpp

@@ -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);
+    }
 }
 
 

+ 30 - 0
test/entt/core/any.cpp

@@ -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);