ソースを参照

any:
* introduce any_policy
* deprecate ::owner member
* add ::policy member

Michele Caini 2 年 前
コミット
b45cf33eef
2 ファイル変更160 行追加24 行削除
  1. 35 24
      src/entt/core/any.hpp
  2. 125 0
      test/entt/core/any.cpp

+ 35 - 24
src/entt/core/any.hpp

@@ -30,12 +30,6 @@ enum class any_operation : std::uint8_t {
     get
 };
 
-enum class any_policy : std::uint8_t {
-    owner,
-    ref,
-    cref
-};
-
 } // namespace internal
 
 /**
@@ -43,6 +37,16 @@ enum class any_policy : std::uint8_t {
  * @endcond
  */
 
+/*! @brief Possible modes of an any object. */
+enum class any_policy : std::uint8_t {
+    /*! @brief Default mode, the object owns the contained element. */
+    owner,
+    /*! @brief Aliasing mode, the object _points_ to a non-const element. */
+    ref,
+    /*! @brief Const aliasing mode, the object _points_ to a const element. */
+    cref
+};
+
 /**
  * @brief A SBO friendly, type-safe container for single values of any type.
  * @tparam Len Size of the storage reserved for the small buffer optimization.
@@ -51,7 +55,6 @@ enum class any_policy : std::uint8_t {
 template<std::size_t Len, std::size_t Align>
 class basic_any {
     using operation = internal::any_operation;
-    using policy = internal::any_policy;
     using vtable_type = const void *(const operation, const basic_any &, const void *);
 
     struct storage_type {
@@ -67,7 +70,7 @@ class basic_any {
         const Type *element = nullptr;
 
         if constexpr(in_situ<Type>) {
-            element = value.owner() ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
+            element = (value.mode == any_policy::owner) ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance);
         } else {
             element = static_cast<const Type *>(value.instance);
         }
@@ -80,7 +83,7 @@ class basic_any {
             break;
         case operation::move:
             if constexpr(in_situ<Type>) {
-                if(value.owner()) {
+                if(value.mode == any_policy::owner) {
                     return new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(element))};
                 }
             }
@@ -129,7 +132,7 @@ class basic_any {
 
             if constexpr(std::is_lvalue_reference_v<Type>) {
                 static_assert((std::is_lvalue_reference_v<Args> && ...) && (sizeof...(Args) == 1u), "Invalid arguments");
-                mode = std::is_const_v<std::remove_reference_t<Type>> ? policy::cref : policy::ref;
+                mode = std::is_const_v<std::remove_reference_t<Type>> ? any_policy::cref : any_policy::ref;
                 instance = (std::addressof(args), ...);
             } else if constexpr(in_situ<std::remove_cv_t<std::remove_reference_t<Type>>>) {
                 if constexpr(std::is_aggregate_v<std::remove_cv_t<std::remove_reference_t<Type>>> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<std::remove_cv_t<std::remove_reference_t<Type>>>)) {
@@ -147,7 +150,7 @@ class basic_any {
         }
     }
 
-    basic_any(const basic_any &other, const policy pol) noexcept
+    basic_any(const basic_any &other, const any_policy pol) noexcept
         : instance{other.data()},
           info{other.info},
           vtable{other.vtable},
@@ -174,7 +177,7 @@ public:
         : instance{},
           info{},
           vtable{},
-          mode{policy::owner} {
+          mode{any_policy::owner} {
         initialize<Type>(std::forward<Args>(args)...);
     }
 
@@ -214,7 +217,7 @@ public:
 
     /*! @brief Frees the internal storage, whatever it means. */
     ~basic_any() {
-        if(vtable && owner()) {
+        if(vtable && (mode == any_policy::owner)) {
             vtable(operation::destroy, *this, nullptr);
         }
     }
@@ -295,7 +298,7 @@ public:
      * @return An opaque pointer the contained instance, if any.
      */
     [[nodiscard]] void *data() noexcept {
-        return mode == policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data());
+        return mode == any_policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data());
     }
 
     /**
@@ -304,7 +307,7 @@ public:
      * @return An opaque pointer the contained instance, if any.
      */
     [[nodiscard]] void *data(const type_info &req) noexcept {
-        return mode == policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
+        return mode == any_policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data(req));
     }
 
     /**
@@ -325,7 +328,7 @@ public:
      * @return True in case of success, false otherwise.
      */
     bool assign(const basic_any &other) {
-        if(vtable && mode != policy::cref && *info == *other.info) {
+        if(vtable && mode != any_policy::cref && *info == *other.info) {
             return (vtable(operation::assign, *this, other.data()) != nullptr);
         }
 
@@ -334,7 +337,7 @@ public:
 
     /*! @copydoc assign */
     bool assign(basic_any &&other) {
-        if(vtable && mode != policy::cref && *info == *other.info) {
+        if(vtable && mode != any_policy::cref && *info == *other.info) {
             if(auto *val = other.data(); val) {
                 return (vtable(operation::transfer, *this, val) != nullptr);
             } else {
@@ -347,7 +350,7 @@ public:
 
     /*! @brief Destroys contained object */
     void reset() {
-        if(vtable && owner()) {
+        if(vtable && (mode == any_policy::owner)) {
             vtable(operation::destroy, *this, nullptr);
         }
 
@@ -355,7 +358,7 @@ public:
         ENTT_ASSERT((instance = nullptr) == nullptr, "");
         info = &type_id<void>();
         vtable = nullptr;
-        mode = policy::owner;
+        mode = any_policy::owner;
     }
 
     /**
@@ -393,20 +396,28 @@ public:
      * @return A wrapper that shares a reference to an unmanaged object.
      */
     [[nodiscard]] basic_any as_ref() noexcept {
-        return basic_any{*this, (mode == policy::cref ? policy::cref : policy::ref)};
+        return basic_any{*this, (mode == any_policy::cref ? any_policy::cref : any_policy::ref)};
     }
 
     /*! @copydoc as_ref */
     [[nodiscard]] basic_any as_ref() const noexcept {
-        return basic_any{*this, policy::cref};
+        return basic_any{*this, any_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 noexcept {
-        return (mode == policy::owner);
+    [[deprecated("use policy() and any_policy instead")]] [[nodiscard]] bool owner() const noexcept {
+        return (mode == any_policy::owner);
+    }
+
+    /**
+     * @brief Returns the current mode of an any object.
+     * @return The current mode of the any object.
+     */
+    [[nodiscard]] any_policy policy() const noexcept {
+        return mode;
     }
 
 private:
@@ -416,7 +427,7 @@ private:
     };
     const type_info *info;
     vtable_type *vtable;
-    policy mode;
+    any_policy mode;
 };
 
 /**

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

@@ -68,6 +68,7 @@ TEST_F(Any, SBO) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::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');
@@ -79,6 +80,7 @@ TEST_F(Any, NoSBO) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::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);
@@ -89,6 +91,7 @@ TEST_F(Any, Empty) {
 
     ASSERT_FALSE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
     ASSERT_EQ(any.data(), nullptr);
@@ -99,6 +102,7 @@ TEST_F(Any, SBOInPlaceTypeConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::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);
@@ -107,6 +111,7 @@ TEST_F(Any, SBOInPlaceTypeConstruction) {
 
     ASSERT_TRUE(other);
     ASSERT_FALSE(other.owner());
+    ASSERT_EQ(other.policy(), entt::any_policy::ref);
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(other), 42);
     ASSERT_EQ(other.data(), any.data());
@@ -118,6 +123,7 @@ TEST_F(Any, SBOAsRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::ref);
     ASSERT_EQ(any.type(), entt::type_id<int>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -136,6 +142,7 @@ TEST_F(Any, SBOAsRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::ref);
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&any), &value);
 
@@ -143,6 +150,7 @@ TEST_F(Any, SBOAsRefConstruction) {
 
     ASSERT_TRUE(other);
     ASSERT_FALSE(other.owner());
+    ASSERT_EQ(other.policy(), entt::any_policy::ref);
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(other), 42);
     ASSERT_EQ(other.data(), any.data());
@@ -154,6 +162,7 @@ TEST_F(Any, SBOAsConstRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::cref);
     ASSERT_EQ(any.type(), entt::type_id<int>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -172,6 +181,7 @@ TEST_F(Any, SBOAsConstRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::cref);
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<const int>(&any), &value);
 
@@ -179,6 +189,7 @@ TEST_F(Any, SBOAsConstRefConstruction) {
 
     ASSERT_TRUE(other);
     ASSERT_FALSE(other.owner());
+    ASSERT_EQ(other.policy(), entt::any_policy::cref);
     ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(other), 42);
     ASSERT_EQ(other.data(), any.data());
@@ -192,6 +203,8 @@ TEST_F(Any, SBOCopyConstruction) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::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);
@@ -208,6 +221,8 @@ TEST_F(Any, SBOCopyAssignment) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::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);
@@ -222,6 +237,8 @@ TEST_F(Any, SBOMoveConstruction) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_NE(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(other.type(), entt::type_id<int>());
@@ -239,6 +256,8 @@ TEST_F(Any, SBOMoveAssignment) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_NE(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<int>());
     ASSERT_EQ(other.type(), entt::type_id<int>());
@@ -252,6 +271,7 @@ TEST_F(Any, SBODirectAssignment) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::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);
@@ -354,6 +374,7 @@ TEST_F(Any, NoSBOInPlaceTypeConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::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);
@@ -362,6 +383,7 @@ TEST_F(Any, NoSBOInPlaceTypeConstruction) {
 
     ASSERT_TRUE(other);
     ASSERT_FALSE(other.owner());
+    ASSERT_EQ(other.policy(), entt::any_policy::ref);
     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());
@@ -373,6 +395,8 @@ TEST_F(Any, NoSBOAsRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::ref);
+    ASSERT_EQ(any.policy(), entt::any_policy::ref);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -391,6 +415,7 @@ TEST_F(Any, NoSBOAsRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::ref);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<fat>(&any), &instance);
 
@@ -398,6 +423,7 @@ TEST_F(Any, NoSBOAsRefConstruction) {
 
     ASSERT_TRUE(other);
     ASSERT_FALSE(other.owner());
+    ASSERT_EQ(other.policy(), entt::any_policy::ref);
     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());
@@ -409,6 +435,7 @@ TEST_F(Any, NoSBOAsConstRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::cref);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
 
     ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
@@ -427,6 +454,7 @@ TEST_F(Any, NoSBOAsConstRefConstruction) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::cref);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(entt::any_cast<const fat>(&any), &instance);
 
@@ -434,6 +462,7 @@ TEST_F(Any, NoSBOAsConstRefConstruction) {
 
     ASSERT_TRUE(other);
     ASSERT_FALSE(other.owner());
+    ASSERT_EQ(other.policy(), entt::any_policy::cref);
     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());
@@ -448,6 +477,8 @@ TEST_F(Any, NoSBOCopyConstruction) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::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);
@@ -465,6 +496,8 @@ TEST_F(Any, NoSBOCopyAssignment) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::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);
@@ -480,6 +513,8 @@ TEST_F(Any, NoSBOMoveConstruction) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
@@ -498,6 +533,8 @@ TEST_F(Any, NoSBOMoveAssignment) {
     ASSERT_TRUE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.data(), nullptr);
     ASSERT_EQ(any.type(), entt::type_id<fat>());
     ASSERT_EQ(other.type(), entt::type_id<fat>());
@@ -512,6 +549,7 @@ TEST_F(Any, NoSBODirectAssignment) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::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);
@@ -628,6 +666,7 @@ TEST_F(Any, VoidInPlaceTypeConstruction) {
 
     ASSERT_FALSE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
 }
@@ -640,6 +679,8 @@ TEST_F(Any, VoidCopyConstruction) {
     ASSERT_FALSE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
     ASSERT_EQ(other.type(), entt::type_id<void>());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -656,6 +697,8 @@ TEST_F(Any, VoidCopyAssignment) {
     ASSERT_FALSE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
     ASSERT_EQ(other.type(), entt::type_id<void>());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -670,6 +713,8 @@ TEST_F(Any, VoidMoveConstruction) {
     ASSERT_FALSE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
     ASSERT_EQ(other.type(), entt::type_id<void>());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -686,6 +731,8 @@ TEST_F(Any, VoidMoveAssignment) {
     ASSERT_FALSE(other);
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
     ASSERT_EQ(other.type(), entt::type_id<void>());
     ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
@@ -758,6 +805,7 @@ TEST_F(Any, Emplace) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::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);
@@ -769,6 +817,7 @@ TEST_F(Any, EmplaceVoid) {
 
     ASSERT_FALSE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
 }
 
@@ -777,12 +826,14 @@ TEST_F(Any, Reset) {
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<int>());
 
     any.reset();
 
     ASSERT_FALSE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
 
     int value = 42;
@@ -790,12 +841,14 @@ TEST_F(Any, Reset) {
 
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::ref);
     ASSERT_EQ(any.type(), entt::type_id<int>());
 
     any.reset();
 
     ASSERT_FALSE(any);
     ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), entt::type_id<void>());
 }
 
@@ -808,6 +861,9 @@ TEST_F(Any, SBOSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_TRUE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::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);
@@ -825,6 +881,9 @@ TEST_F(Any, NoSBOSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_TRUE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::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}));
 }
@@ -839,6 +898,9 @@ TEST_F(Any, VoidSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_TRUE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::owner);
+
     ASSERT_EQ(pre, lhs.data());
 }
 
@@ -851,6 +913,9 @@ TEST_F(Any, SBOWithNoSBOSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_TRUE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::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);
@@ -869,6 +934,9 @@ TEST_F(Any, SBOWithRefSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_FALSE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::ref);
+
     ASSERT_EQ(lhs.type(), entt::type_id<char>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -888,6 +956,9 @@ TEST_F(Any, SBOWithConstRefSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_FALSE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::cref);
+
     ASSERT_EQ(lhs.type(), entt::type_id<char>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -906,6 +977,7 @@ TEST_F(Any, SBOWithEmptySwap) {
 
     ASSERT_FALSE(lhs);
     ASSERT_TRUE(lhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -915,6 +987,7 @@ TEST_F(Any, SBOWithEmptySwap) {
 
     ASSERT_FALSE(rhs);
     ASSERT_TRUE(rhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -929,6 +1002,7 @@ TEST_F(Any, SBOWithVoidSwap) {
 
     ASSERT_FALSE(lhs);
     ASSERT_TRUE(lhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -938,6 +1012,7 @@ TEST_F(Any, SBOWithVoidSwap) {
 
     ASSERT_FALSE(rhs);
     ASSERT_TRUE(rhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -954,6 +1029,9 @@ TEST_F(Any, NoSBOWithRefSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_FALSE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::ref);
+
     ASSERT_EQ(lhs.type(), entt::type_id<fat>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -973,6 +1051,9 @@ TEST_F(Any, NoSBOWithConstRefSwap) {
     ASSERT_TRUE(lhs.owner());
     ASSERT_FALSE(rhs.owner());
 
+    ASSERT_EQ(lhs.policy(), entt::any_policy::owner);
+    ASSERT_EQ(rhs.policy(), entt::any_policy::cref);
+
     ASSERT_EQ(lhs.type(), entt::type_id<fat>());
     ASSERT_EQ(rhs.type(), entt::type_id<int>());
     ASSERT_EQ(entt::any_cast<int>(&lhs), nullptr);
@@ -991,6 +1072,7 @@ TEST_F(Any, NoSBOWithEmptySwap) {
 
     ASSERT_FALSE(lhs);
     ASSERT_TRUE(lhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -1000,6 +1082,7 @@ TEST_F(Any, NoSBOWithEmptySwap) {
 
     ASSERT_FALSE(rhs);
     ASSERT_TRUE(rhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -1014,6 +1097,7 @@ TEST_F(Any, NoSBOWithVoidSwap) {
 
     ASSERT_FALSE(lhs);
     ASSERT_TRUE(lhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -1023,6 +1107,7 @@ TEST_F(Any, NoSBOWithVoidSwap) {
 
     ASSERT_FALSE(rhs);
     ASSERT_TRUE(rhs.owner());
+    ASSERT_EQ(lhs.policy(), entt::any_policy::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);
@@ -1037,6 +1122,9 @@ TEST_F(Any, AsRef) {
     ASSERT_FALSE(ref.owner());
     ASSERT_FALSE(cref.owner());
 
+    ASSERT_EQ(ref.policy(), entt::any_policy::ref);
+    ASSERT_EQ(cref.policy(), entt::any_policy::cref);
+
     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);
@@ -1071,6 +1159,9 @@ TEST_F(Any, AsRef) {
     ASSERT_FALSE(ref.owner());
     ASSERT_FALSE(cref.owner());
 
+    ASSERT_EQ(ref.policy(), entt::any_policy::cref);
+    ASSERT_EQ(cref.policy(), entt::any_policy::ref);
+
     ASSERT_EQ(entt::any_cast<int>(&ref), nullptr);
     ASSERT_EQ(entt::any_cast<int>(&cref), any.data());
 
@@ -1080,6 +1171,9 @@ TEST_F(Any, AsRef) {
     ASSERT_FALSE(ref.owner());
     ASSERT_FALSE(cref.owner());
 
+    ASSERT_EQ(ref.policy(), entt::any_policy::cref);
+    ASSERT_EQ(cref.policy(), entt::any_policy::cref);
+
     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());
@@ -1097,6 +1191,9 @@ TEST_F(Any, AsRef) {
     ASSERT_TRUE(ref.owner());
     ASSERT_TRUE(cref.owner());
 
+    ASSERT_EQ(ref.policy(), entt::any_policy::owner);
+    ASSERT_EQ(cref.policy(), entt::any_policy::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);
@@ -1210,6 +1307,10 @@ TEST_F(Any, MakeAny) {
     ASSERT_TRUE(ext.owner());
     ASSERT_FALSE(ref.owner());
 
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(ext.policy(), entt::any_policy::owner);
+    ASSERT_EQ(ref.policy(), entt::any_policy::ref);
+
     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);
@@ -1237,6 +1338,10 @@ TEST_F(Any, ForwardAsAny) {
     ASSERT_FALSE(ref.owner());
     ASSERT_FALSE(cref.owner());
 
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(ref.policy(), entt::any_policy::ref);
+    ASSERT_EQ(cref.policy(), entt::any_policy::cref);
+
     ASSERT_NE(entt::any_cast<int>(&any), nullptr);
     ASSERT_NE(entt::any_cast<int>(&ref), nullptr);
     ASSERT_EQ(entt::any_cast<int>(&cref), nullptr);
@@ -1259,6 +1364,8 @@ TEST_F(Any, NotCopyableType) {
 
     ASSERT_TRUE(any.owner());
     ASSERT_FALSE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::cref);
     ASSERT_EQ(any.type(), other.type());
 
     ASSERT_FALSE(any.assign(other));
@@ -1272,6 +1379,9 @@ TEST_F(Any, NotCopyableType) {
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(copy.owner());
 
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(copy.policy(), entt::any_policy::owner);
+
     copy = any;
 
     ASSERT_TRUE(any);
@@ -1279,6 +1389,9 @@ TEST_F(Any, NotCopyableType) {
 
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(copy.owner());
+
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(copy.policy(), entt::any_policy::owner);
 }
 
 TEST_F(Any, NotCopyableValueType) {
@@ -1307,6 +1420,8 @@ TEST_F(Any, NotMovableType) {
 
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(other.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(other.policy(), entt::any_policy::owner);
     ASSERT_EQ(any.type(), other.type());
 
     ASSERT_TRUE(any.assign(other));
@@ -1320,6 +1435,9 @@ TEST_F(Any, NotMovableType) {
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(copy.owner());
 
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(copy.policy(), entt::any_policy::owner);
+
     copy = any;
 
     ASSERT_TRUE(any);
@@ -1327,6 +1445,9 @@ TEST_F(Any, NotMovableType) {
 
     ASSERT_TRUE(any.owner());
     ASSERT_TRUE(copy.owner());
+
+    ASSERT_EQ(any.policy(), entt::any_policy::owner);
+    ASSERT_EQ(copy.policy(), entt::any_policy::owner);
 }
 
 TEST_F(Any, Array) {
@@ -1364,6 +1485,10 @@ TEST_F(Any, CopyMoveReference) {
         ASSERT_FALSE(move.owner());
         ASSERT_TRUE(copy.owner());
 
+        ASSERT_EQ(any.policy(), std::is_const_v<std::remove_reference_t<decltype(ref)>> ? entt::any_policy::cref : entt::any_policy::ref);
+        ASSERT_EQ(move.policy(), std::is_const_v<std::remove_reference_t<decltype(ref)>> ? entt::any_policy::cref : entt::any_policy::ref);
+        ASSERT_EQ(copy.policy(), entt::any_policy::owner);
+
         ASSERT_EQ(move.type(), entt::type_id<int>());
         ASSERT_EQ(copy.type(), entt::type_id<int>());