Просмотр исходного кода

any: ::owner function (useful to also review meta_any)

Michele Caini 4 лет назад
Родитель
Сommit
77afd2d36c
2 измененных файлов с 142 добавлено и 9 удалено
  1. 17 9
      src/entt/core/any.hpp
  2. 125 0
      test/entt/core/any.cpp

+ 17 - 9
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: std::uint8_t { COPY, MOVE, DTOR, COMP, ADDR, CADDR, TYPE };
-    enum class policy: std::uint8_t { OWNED, REF, CREF };
+    enum class policy: std::uint8_t { OWNER, REF, CREF };
 
     using storage_type = std::aligned_storage_t<Len + !Len, Align>;
     using vtable_type = const void *(const operation, const basic_any &, void *);
@@ -42,7 +42,7 @@ class basic_any {
                 return policy::REF;
             }
         } else {
-            return policy::OWNED;
+            return policy::OWNER;
         }
     }
 
@@ -60,7 +60,7 @@ class basic_any {
         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>) {
-            const Type *instance = (in_situ<Type> && from.mode == policy::OWNED)
+            const Type *instance = (in_situ<Type> && from.mode == policy::OWNER)
                 ? ENTT_LAUNDER(reinterpret_cast<const Type *>(&from.storage))
                 : static_cast<const Type *>(from.instance);
 
@@ -72,14 +72,14 @@ class basic_any {
                 break;
             case operation::MOVE:
                 if constexpr(in_situ<Type>) {
-                    if(from.mode == policy::OWNED) {
+                    if(from.mode == policy::OWNER) {
                         return new (&static_cast<basic_any *>(to)->storage) Type{std::move(*const_cast<Type *>(instance))};
                     }
                 }
 
                 return (static_cast<basic_any *>(to)->instance = std::exchange(const_cast<basic_any &>(from).instance, nullptr));
             case operation::DTOR:
-                if(from.mode == policy::OWNED) {
+                if(from.mode == policy::OWNER) {
                     if constexpr(in_situ<Type>) {
                         instance->~Type();
                     } else if constexpr(std::is_array_v<Type>) {
@@ -145,7 +145,7 @@ public:
     basic_any() ENTT_NOEXCEPT
         : instance{},
           vtable{&basic_vtable<void>},
-          mode{policy::OWNED}
+          mode{policy::OWNER}
     {}
 
     /**
@@ -185,7 +185,7 @@ public:
     basic_any(Type &&value)
         : instance{},
           vtable{&basic_vtable<std::decay_t<Type>>},
-          mode{policy::OWNED}
+          mode{policy::OWNER}
     {
         initialize<std::decay_t<Type>>(std::forward<Type>(value));
     }
@@ -197,7 +197,7 @@ public:
     basic_any(const basic_any &other)
         : instance{},
           vtable{&basic_vtable<void>},
-          mode{policy::OWNED}
+          mode{policy::OWNER}
     {
         other.vtable(operation::COPY, other, this);
     }
@@ -307,7 +307,7 @@ public:
     /*! @brief Destroys contained object */
     void reset() {
         std::exchange(vtable, &basic_vtable<void>)(operation::DTOR, *this, nullptr);
-        mode = policy::OWNED;
+        mode = policy::OWNER;
     }
 
     /**
@@ -341,6 +341,14 @@ public:
         return basic_any{*this, policy::CREF};
     }
 
+    /**
+     * @brief Returns true if a wrapper owns its object, false otherwise.
+     * @return True if the wrapper owns its object, false otherwise.
+     */
+    [[nodiscard]] bool owner() const ENTT_NOEXCEPT {
+        return (mode == policy::OWNER);
+    }
+
 private:
     union { const void *instance; storage_type storage; };
     vtable_type *vtable;

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

@@ -52,6 +52,7 @@ TEST_F(Any, SBO) {
     entt::any any{'c'};
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<char>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(entt::any_cast<char>(any), 'c');
@@ -62,6 +63,7 @@ TEST_F(Any, NoSBO) {
     entt::any any{instance};
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(entt::any_cast<fat>(any), instance);
@@ -71,6 +73,7 @@ TEST_F(Any, Empty) {
     entt::any any{};
 
     ASSERT_FALSE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_FALSE(any.type());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(any.data(), nullptr);
@@ -80,6 +83,7 @@ TEST_F(Any, SBOInPlaceTypeConstruction) {
     entt::any any{std::in_place_type<int>, 42};
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(entt::any_cast<int>(any), 42);
@@ -87,6 +91,7 @@ TEST_F(Any, SBOInPlaceTypeConstruction) {
     auto other = any.as_ref();
 
     ASSERT_TRUE(other);
+    ASSERT_FALSE(other.owner());
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(other), 42);
     ASSERT_EQ(other.data(), any.data());
@@ -97,6 +102,7 @@ TEST_F(Any, SBOAsRefConstruction) {
     entt::any any{entt::forward_as_any(value)};
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -114,12 +120,14 @@ TEST_F(Any, SBOAsRefConstruction) {
     any.emplace<int &>(value);
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&any), &value);
 
     auto other = any.as_ref();
 
     ASSERT_TRUE(other);
+    ASSERT_FALSE(other.owner());
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(other), 42);
     ASSERT_EQ(other.data(), any.data());
@@ -130,6 +138,7 @@ TEST_F(Any, SBOAsConstRefConstruction) {
     entt::any any{entt::forward_as_any(value)};
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -147,12 +156,14 @@ TEST_F(Any, SBOAsConstRefConstruction) {
     any.emplace<const int &>(value);
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<const int>(&any), &value);
 
     auto other = any.as_ref();
 
     ASSERT_TRUE(other);
+    ASSERT_FALSE(other.owner());
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(other), 42);
     ASSERT_EQ(other.data(), any.data());
@@ -164,6 +175,8 @@ TEST_F(Any, SBOCopyConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
@@ -178,6 +191,8 @@ TEST_F(Any, SBOCopyAssignment) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
@@ -190,6 +205,8 @@ TEST_F(Any, SBOMoveConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_NE(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(other.type(), entt::type_id<int>());
@@ -205,6 +222,8 @@ TEST_F(Any, SBOMoveAssignment) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_NE(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(other.type(), entt::type_id<int>());
@@ -217,6 +236,7 @@ TEST_F(Any, SBODirectAssignment) {
     any = 42;
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(entt::any_cast<int>(any), 42);
@@ -227,6 +247,7 @@ TEST_F(Any, NoSBOInPlaceTypeConstruction) {
     entt::any any{std::in_place_type<fat>, instance};
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(entt::any_cast<fat>(any), instance);
@@ -234,6 +255,7 @@ TEST_F(Any, NoSBOInPlaceTypeConstruction) {
     auto other = any.as_ref();
 
     ASSERT_TRUE(other);
+    ASSERT_FALSE(other.owner());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(other), (fat{.1, .2, .3, .4}));
     ASSERT_EQ(other.data(), any.data());
@@ -244,6 +266,7 @@ TEST_F(Any, NoSBOAsRefConstruction) {
     entt::any any{entt::forward_as_any(instance)};
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -261,12 +284,14 @@ TEST_F(Any, NoSBOAsRefConstruction) {
     any.emplace<fat &>(instance);
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(&any), &instance);
 
     auto other = any.as_ref();
 
     ASSERT_TRUE(other);
+    ASSERT_FALSE(other.owner());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(other), (fat{.1, .2, .3, .4}));
     ASSERT_EQ(other.data(), any.data());
@@ -277,6 +302,7 @@ TEST_F(Any, NoSBOAsConstRefConstruction) {
     entt::any any{entt::forward_as_any(instance)};
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -294,12 +320,14 @@ TEST_F(Any, NoSBOAsConstRefConstruction) {
     any.emplace<const fat &>(instance);
 
     ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<const fat>(&any), &instance);
 
     auto other = any.as_ref();
 
     ASSERT_TRUE(other);
+    ASSERT_FALSE(other.owner());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(other), (fat{.1, .2, .3, .4}));
     ASSERT_EQ(other.data(), any.data());
@@ -312,6 +340,8 @@ TEST_F(Any, NoSBOCopyConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
@@ -327,6 +357,8 @@ TEST_F(Any, NoSBOCopyAssignment) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
@@ -340,6 +372,8 @@ TEST_F(Any, NoSBOMoveConstruction) {
 
     ASSERT_FALSE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_EQ(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
@@ -356,6 +390,8 @@ TEST_F(Any, NoSBOMoveAssignment) {
 
     ASSERT_FALSE(any);
     ASSERT_TRUE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_EQ(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
@@ -369,6 +405,7 @@ TEST_F(Any, NoSBODirectAssignment) {
     any = instance;
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(entt::any_cast<fat>(any), instance);
@@ -378,6 +415,7 @@ TEST_F(Any, VoidInPlaceTypeConstruction) {
     entt::any any{std::in_place_type<void>};
 
     ASSERT_FALSE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_FALSE(any.type());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
 }
@@ -388,6 +426,8 @@ TEST_F(Any, VoidCopyConstruction) {
 
     ASSERT_FALSE(any);
     ASSERT_FALSE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_FALSE(any.type());
     ASSERT_FALSE(other.type());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -402,6 +442,8 @@ TEST_F(Any, VoidCopyAssignment) {
 
     ASSERT_FALSE(any);
     ASSERT_FALSE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_FALSE(any.type());
     ASSERT_FALSE(other.type());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -414,6 +456,8 @@ TEST_F(Any, VoidMoveConstruction) {
 
     ASSERT_FALSE(any);
     ASSERT_FALSE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_FALSE(any.type());
     ASSERT_FALSE(other.type());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -428,6 +472,8 @@ TEST_F(Any, VoidMoveAssignment) {
 
     ASSERT_FALSE(any);
     ASSERT_FALSE(other);
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(other.owner());
     ASSERT_FALSE(any.type());
     ASSERT_FALSE(other.type());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -499,6 +545,7 @@ TEST_F(Any, Emplace) {
     any.emplace<int>(42);
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(entt::any_cast<int>(any), 42);
@@ -509,6 +556,7 @@ TEST_F(Any, EmplaceVoid) {
     any.emplace<void>();
 
     ASSERT_FALSE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_FALSE(any.type());
  }
 
@@ -516,11 +564,26 @@ TEST_F(Any, Reset) {
     entt::any any{42};
 
     ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_id<int>());
 
     any.reset();
 
     ASSERT_FALSE(any);
+    ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.type(), entt::type_info{});
+
+    int value = 42;
+    any.emplace<int &>(value);
+
+    ASSERT_TRUE(any);
+    ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.type(), entt::type_id<int>());
+
+    any.reset();
+
+    ASSERT_FALSE(any);
+    ASSERT_TRUE(any.owner());
     ASSERT_EQ(any.type(), entt::type_info{});
 }
 
@@ -530,6 +593,9 @@ TEST_F(Any, SBOSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_TRUE(rhs.owner());
+
     ASSERT_EQ(lhs.type(), entt::type_id<int>());
     ASSERT_EQ(rhs.type(), entt::type_id<char>());
     ASSERT_EQ(entt::any_cast<char>(&lhs), nullptr);
@@ -544,6 +610,9 @@ TEST_F(Any, NoSBOSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_TRUE(rhs.owner());
+
     ASSERT_EQ(entt::any_cast<fat>(lhs), (fat{.4, .3, .2, .1}));
     ASSERT_EQ(entt::any_cast<fat>(rhs), (fat{.1, .2, .3, .4}));
 }
@@ -555,6 +624,9 @@ TEST_F(Any, VoidSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_TRUE(rhs.owner());
+
     ASSERT_EQ(pre, lhs.data());
 }
 
@@ -564,6 +636,9 @@ TEST_F(Any, SBOWithNoSBOSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_TRUE(rhs.owner());
+
     ASSERT_EQ(lhs.type(), entt::type_id<char>());
     ASSERT_EQ(rhs.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(&lhs), nullptr);
@@ -579,6 +654,9 @@ TEST_F(Any, SBOWithRefSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_FALSE(rhs.owner());
+
     ASSERT_EQ(lhs.type(), entt::type_id<char>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -595,6 +673,9 @@ TEST_F(Any, SBOWithConstRefSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_FALSE(rhs.owner());
+
     ASSERT_EQ(lhs.type(), entt::type_id<char>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -612,6 +693,7 @@ TEST_F(Any, SBOWithEmptySwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(lhs);
+    ASSERT_TRUE(lhs.owner());
     ASSERT_EQ(rhs.type(), entt::type_id<char>());
     ASSERT_EQ(entt::any_cast<char>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<double>(&rhs), nullptr);
@@ -620,6 +702,7 @@ TEST_F(Any, SBOWithEmptySwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(rhs);
+    ASSERT_TRUE(rhs.owner());
     ASSERT_EQ(lhs.type(), entt::type_id<char>());
     ASSERT_EQ(entt::any_cast<double>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<char>(&rhs), nullptr);
@@ -633,6 +716,7 @@ TEST_F(Any, SBOWithVoidSwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(lhs);
+    ASSERT_TRUE(lhs.owner());
     ASSERT_EQ(rhs.type(), entt::type_id<char>());
     ASSERT_EQ(entt::any_cast<char>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<double>(&rhs), nullptr);
@@ -641,6 +725,7 @@ TEST_F(Any, SBOWithVoidSwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(rhs);
+    ASSERT_TRUE(rhs.owner());
     ASSERT_EQ(lhs.type(), entt::type_id<char>());
     ASSERT_EQ(entt::any_cast<double>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<char>(&rhs), nullptr);
@@ -654,6 +739,9 @@ TEST_F(Any, NoSBOWithRefSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_FALSE(rhs.owner());
+
     ASSERT_EQ(lhs.type(), entt::type_id<fat>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -670,6 +758,9 @@ TEST_F(Any, NoSBOWithConstRefSwap) {
 
     std::swap(lhs, rhs);
 
+    ASSERT_TRUE(lhs.owner());
+    ASSERT_FALSE(rhs.owner());
+
     ASSERT_EQ(lhs.type(), entt::type_id<fat>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -687,6 +778,7 @@ TEST_F(Any, NoSBOWithEmptySwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(lhs);
+    ASSERT_TRUE(lhs.owner());
     ASSERT_EQ(rhs.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<double>(&rhs), nullptr);
@@ -695,6 +787,7 @@ TEST_F(Any, NoSBOWithEmptySwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(rhs);
+    ASSERT_TRUE(rhs.owner());
     ASSERT_EQ(lhs.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<double>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<fat>(&rhs), nullptr);
@@ -708,6 +801,7 @@ TEST_F(Any, NoSBOWithVoidSwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(lhs);
+    ASSERT_TRUE(lhs.owner());
     ASSERT_EQ(rhs.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<double>(&rhs), nullptr);
@@ -716,6 +810,7 @@ TEST_F(Any, NoSBOWithVoidSwap) {
     std::swap(lhs, rhs);
 
     ASSERT_FALSE(rhs);
+    ASSERT_TRUE(rhs.owner());
     ASSERT_EQ(lhs.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<double>(&lhs), nullptr);
     ASSERT_EQ(entt::any_cast<fat>(&rhs), nullptr);
@@ -727,6 +822,9 @@ TEST_F(Any, AsRef) {
     auto ref = any.as_ref();
     auto cref = std::as_const(any).as_ref();
 
+    ASSERT_FALSE(ref.owner());
+    ASSERT_FALSE(cref.owner());
+
     ASSERT_EQ(entt::any_cast<int>(&any), any.data());
     ASSERT_EQ(entt::any_cast<int>(&ref), any.data());
     ASSERT_EQ(entt::any_cast<int>(&cref), nullptr);
@@ -758,12 +856,18 @@ TEST_F(Any, AsRef) {
 
     std::swap(ref, cref);
 
+    ASSERT_FALSE(ref.owner());
+    ASSERT_FALSE(cref.owner());
+
     ASSERT_EQ(entt::any_cast<int>(&ref), nullptr);
     ASSERT_EQ(entt::any_cast<int>(&cref), any.data());
 
     ref = ref.as_ref();
     cref = std::as_const(cref).as_ref();
 
+    ASSERT_FALSE(ref.owner());
+    ASSERT_FALSE(cref.owner());
+
     ASSERT_EQ(entt::any_cast<int>(&ref), nullptr);
     ASSERT_EQ(entt::any_cast<int>(&cref), nullptr);
     ASSERT_EQ(entt::any_cast<const int>(&ref), any.data());
@@ -778,6 +882,9 @@ TEST_F(Any, AsRef) {
     ref = 42;
     cref = 42;
 
+    ASSERT_TRUE(ref.owner());
+    ASSERT_TRUE(cref.owner());
+
     ASSERT_NE(entt::any_cast<int>(&ref), nullptr);
     ASSERT_NE(entt::any_cast<int>(&cref), nullptr);
     ASSERT_EQ(entt::any_cast<int &>(ref), 42);
@@ -867,6 +974,10 @@ TEST_F(Any, MakeAny) {
     ASSERT_TRUE(ext);
     ASSERT_TRUE(ref);
 
+    ASSERT_TRUE(any.owner());
+    ASSERT_TRUE(ext.owner());
+    ASSERT_FALSE(ref.owner());
+
     ASSERT_EQ(entt::any_cast<const int &>(any), 42);
     ASSERT_EQ(entt::any_cast<const int &>(ext), 42);
     ASSERT_EQ(entt::any_cast<const int &>(ref), 42);
@@ -890,6 +1001,10 @@ TEST_F(Any, ForwardAsAny) {
     ASSERT_TRUE(ref);
     ASSERT_TRUE(cref);
 
+    ASSERT_TRUE(any.owner());
+    ASSERT_FALSE(ref.owner());
+    ASSERT_FALSE(cref.owner());
+
     ASSERT_NE(entt::any_cast<int>(&any), nullptr);
     ASSERT_NE(entt::any_cast<int>(&ref), nullptr);
     ASSERT_EQ(entt::any_cast<int>(&cref), nullptr);
@@ -909,10 +1024,16 @@ TEST_F(Any, NotCopyableType) {
         ASSERT_TRUE(any);
         ASSERT_FALSE(copy);
 
+        ASSERT_TRUE(any.owner());
+        ASSERT_TRUE(copy.owner());
+
         copy = any;
 
         ASSERT_TRUE(any);
         ASSERT_FALSE(copy);
+
+        ASSERT_TRUE(any.owner());
+        ASSERT_TRUE(copy.owner());
     };
 
     test(entt::any{std::in_place_type<not_copyable<1>>});
@@ -950,6 +1071,10 @@ TEST_F(Any, CopyMoveReference) {
         ASSERT_TRUE(move);
         ASSERT_TRUE(copy);
 
+        ASSERT_FALSE(any.owner());
+        ASSERT_FALSE(move.owner());
+        ASSERT_TRUE(copy.owner());
+
         ASSERT_EQ(move.type(), entt::type_id<int>());
         ASSERT_EQ(copy.type(), entt::type_id<int>());