Przeglądaj źródła

any: reduce vtable options

Michele Caini 4 lat temu
rodzic
commit
e59d40834d
2 zmienionych plików z 18 dodań i 47 usunięć
  1. 17 46
      src/entt/core/any.hpp
  2. 1 1
      test/entt/core/any.cpp

+ 17 - 46
src/entt/core/any.hpp

@@ -25,7 +25,7 @@ namespace entt {
  */
 template<std::size_t Len, std::size_t Align>
 class basic_any {
-    enum class operation { COPY, MOVE, DTOR, COMP, ADDR, CADDR, REF, CREF, TYPE };
+    enum class operation: std::uint8_t { COPY, MOVE, DTOR, COMP, ADDR, CADDR, REF, CREF, TYPE };
 
     using storage_type = std::aligned_storage_t<Len + !Len, Align>;
     using vtable_type = const void *(const operation, const basic_any &, void *);
@@ -53,39 +53,7 @@ class basic_any {
             default:
                 break;
             }
-        } else if constexpr(std::is_lvalue_reference_v<Type>) {
-            using base_type = std::decay_t<Type>;
-
-            switch(op) {
-            case operation::COPY:
-                if constexpr(std::is_copy_constructible_v<base_type>) {
-                    static_cast<basic_any *>(to)->emplace<base_type>(*static_cast<const base_type *>(from.instance));
-                }
-                break;
-            case operation::MOVE:
-                static_cast<basic_any *>(to)->instance = from.instance;
-                [[fallthrough]];
-            case operation::DTOR:
-                break;
-            case operation::COMP:
-                return compare<base_type>(from.instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
-            case operation::ADDR:
-                return std::is_const_v<std::remove_reference_t<Type>> ? nullptr : from.instance;
-            case operation::CADDR:
-                return from.instance;
-            case operation::REF:
-                static_cast<basic_any *>(to)->instance = from.instance;
-                static_cast<basic_any *>(to)->vtable = basic_vtable<Type>;
-                break;
-            case operation::CREF:
-                static_cast<basic_any *>(to)->instance = from.instance;
-                static_cast<basic_any *>(to)->vtable = basic_vtable<const base_type &>;
-                break;
-            case operation::TYPE:
-                *static_cast<type_info *>(to) = type_id<base_type>();
-                break;
-            }
-        } else if constexpr(in_situ<Type>) {
+        } else if constexpr(!std::is_lvalue_reference_v<Type> && in_situ<Type>) {
             #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
             const auto *instance = std::launder(reinterpret_cast<const Type *>(&from.storage));
             #else
@@ -121,11 +89,13 @@ class basic_any {
                 *static_cast<type_info *>(to) = type_id<Type>();
                 break;
             }
-        } else {
+        } else { /* either a reference or a dynamically allocated object */
+            const auto *instance = static_cast<const std::decay_t<Type> *>(from.instance);
+
             switch(op) {
             case operation::COPY:
-                if constexpr(std::is_copy_constructible_v<Type>) {
-                    static_cast<basic_any *>(to)->emplace<Type>(*static_cast<const Type *>(from.instance));
+                if constexpr(std::is_copy_constructible_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
+                    static_cast<basic_any *>(to)->emplace<std::decay_t<Type>>(*instance);
                 }
                 break;
             case operation::MOVE:
@@ -133,26 +103,27 @@ class basic_any {
                 break;
             case operation::DTOR:
                 if constexpr(std::is_array_v<Type>) {
-                    delete[] static_cast<const Type *>(from.instance);
-                } else {
-                    delete static_cast<const Type *>(from.instance);
+                    delete[] instance;
+                } else if constexpr(!std::is_lvalue_reference_v<Type>) {
+                    delete instance;
                 }
                 break;
             case operation::COMP:
-                return compare<Type>(from.instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
+                return compare<std::remove_const_t<std::remove_reference_t<Type>>>(instance, (*static_cast<const basic_any **>(to))->data()) ? to : nullptr;
             case operation::ADDR:
+                return std::is_const_v<std::remove_reference_t<Type>> ? nullptr : instance;
             case operation::CADDR:
-                return from.instance;
+                return instance;
             case operation::REF:
-                static_cast<basic_any *>(to)->instance = from.instance;
+                static_cast<basic_any *>(to)->instance = instance;
                 static_cast<basic_any *>(to)->vtable = basic_vtable<Type &>;
                 break;
             case operation::CREF:
-                static_cast<basic_any *>(to)->instance = from.instance;
-                static_cast<basic_any *>(to)->vtable = basic_vtable<const Type &>;
+                static_cast<basic_any *>(to)->instance = instance;
+                static_cast<basic_any *>(to)->vtable = basic_vtable<const std::remove_reference_t<Type> &>;
                 break;
             case operation::TYPE:
-                *static_cast<type_info *>(to) = type_id<Type>();
+                *static_cast<type_info *>(to) = type_id<std::remove_const_t<std::remove_reference_t<Type>>>();
                 break;
             }
         }

+ 1 - 1
test/entt/core/any.cpp

@@ -901,7 +901,7 @@ TEST_F(Any, CopyMoveReference) {
         entt::any move = std::move(any);
         entt::any copy = move;
 
-        ASSERT_TRUE(any);
+        ASSERT_FALSE(any);
         ASSERT_TRUE(move);
         ASSERT_TRUE(copy);