Explorar o código

any:
* when moving fails, try to copy anyway as a fallback
* code coverage

Michele Caini %!s(int64=4) %!d(string=hai) anos
pai
achega
04b2e1152c
Modificáronse 3 ficheiros con 57 adicións e 7 borrados
  1. 7 1
      docs/md/core.md
  2. 5 5
      src/entt/core/any.hpp
  3. 45 1
      test/entt/core/any.cpp

+ 7 - 1
docs/md/core.md

@@ -270,7 +270,13 @@ the object is used in _aliasing mode_, as described below:
 
 ```cpp
 entt::any any{42};
-any.assign(3);
+entt::any value{3};
+
+// assigns by copy
+any.assign(value);
+
+// assigns by move
+any.assign(std::move(value));
 ```
 
 The `any` class will also perform a check on the type information and whether or

+ 5 - 5
src/entt/core/any.hpp

@@ -67,15 +67,15 @@ class basic_any {
             }
 
             return (static_cast<basic_any *>(const_cast<void *>(to))->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
-        case operation::assign:
-            if constexpr(std::is_copy_assignable_v<Type>) {
-                return std::addressof(*const_cast<Type *>(instance) = *static_cast<const Type *>(to));
-            }
-            break;
         case operation::transfer:
             if constexpr(std::is_move_assignable_v<Type>) {
                 return std::addressof(*const_cast<Type *>(instance) = std::move(*static_cast<Type *>(const_cast<void *>(to))));
             }
+            [[fallthrough]];
+        case operation::assign:
+            if constexpr(std::is_copy_assignable_v<Type>) {
+                return std::addressof(*const_cast<Type *>(instance) = *static_cast<const Type *>(to));
+            }
             break;
         case operation::destroy:
             if constexpr(in_situ<Type>) {

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

@@ -47,6 +47,17 @@ struct not_copyable {
     double payload;
 };
 
+struct not_movable {
+    not_movable() = default;
+    not_movable(const not_movable &) = default;
+    not_movable(not_movable &&) = delete;
+
+    not_movable &operator=(const not_movable &) = default;
+    not_movable &operator=(not_movable &&) = delete;
+
+    double payload;
+};
+
 struct alignas(64u) over_aligned {};
 
 struct Any: ::testing::Test {
@@ -1261,10 +1272,43 @@ TEST_F(Any, NotCopyableType) {
         ASSERT_TRUE(copy.owner());
     };
 
-    const not_copyable value;
+    const not_copyable value{};
     test(entt::any{std::in_place_type<not_copyable>}, entt::forward_as_any(value));
 }
 
+TEST_F(Any, NotMovableType) {
+    auto test = [](entt::any any, entt::any other) {
+        ASSERT_TRUE(any);
+        ASSERT_TRUE(other);
+
+        ASSERT_TRUE(any.owner());
+        ASSERT_TRUE(other.owner());
+        ASSERT_EQ(any.type(), other.type());
+
+        ASSERT_TRUE(any.assign(other));
+        ASSERT_TRUE(any.assign(std::move(other)));
+
+        entt::any copy{any};
+
+        ASSERT_TRUE(any);
+        ASSERT_TRUE(copy);
+
+        ASSERT_TRUE(any.owner());
+        ASSERT_TRUE(copy.owner());
+
+        copy = any;
+
+        ASSERT_TRUE(any);
+        ASSERT_TRUE(copy);
+
+        ASSERT_TRUE(any.owner());
+        ASSERT_TRUE(copy.owner());
+    };
+
+    const not_movable value{};
+    test(entt::any{std::in_place_type<not_movable>}, entt::any{std::in_place_type<not_movable>});
+}
+
 TEST_F(Any, Array) {
     entt::any any{std::in_place_type<int[1]>};
     entt::any copy{any};