Browse Source

any: support taking ownership of passed in pointers

Michele Caini 1 năm trước cách đây
mục cha
commit
5734063de2
2 tập tin đã thay đổi với 82 bổ sung4 xóa
  1. 16 0
      src/entt/core/any.hpp
  2. 66 4
      test/entt/core/any.cpp

+ 16 - 0
src/entt/core/any.hpp

@@ -189,6 +189,22 @@ public:
         initialize<Type>(std::forward<Args>(args)...);
     }
 
+    /**
+     * @brief Constructs a wrapper taking ownership of the passed object.
+     * @tparam Type Type of object to use to initialize the wrapper.
+     * @param value A pointer to an object to take ownership of.
+     */
+    template<typename Type, typename = std::enable_if_t<!std::is_void_v<std::remove_const_t<Type>>>>
+    explicit basic_any(std::in_place_t, Type *value)
+        : instance{value},
+          info{&type_id<std::remove_const_t<Type>>()},
+          vtable{basic_vtable<std::remove_const_t<Type>>},
+          mode{any_policy::dynamic} {
+        if(instance == nullptr) {
+            reset();
+        }
+    }
+
     /**
      * @brief Constructs a wrapper from a given value.
      * @tparam Type Type of object to use to initialize the wrapper.

+ 66 - 4
test/entt/core/any.cpp

@@ -46,6 +46,17 @@ struct fat {
 
 struct alignas(64u) over_aligned {};
 
+TEST(Any, Empty) {
+    entt::any any{};
+
+    ASSERT_FALSE(any);
+    ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::empty);
+    ASSERT_EQ(any.type(), entt::type_id<void>());
+    ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
+    ASSERT_EQ(any.data(), nullptr);
+}
+
 TEST(Any, SBO) {
     entt::any any{'c'};
 
@@ -69,15 +80,35 @@ TEST(Any, NoSBO) {
     ASSERT_EQ(entt::any_cast<fat>(any), instance);
 }
 
-TEST(Any, Empty) {
-    entt::any any{};
+TEST(Any, SBOInPlaceConstruction) {
+    std::unique_ptr<int> instance = std::make_unique<int>(2);
+    entt::any any{std::in_place, instance.release()};
+
+    ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::dynamic);
+    ASSERT_EQ(any.type(), entt::type_id<int>());
+    ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
+    ASSERT_EQ(entt::any_cast<int>(any), 2);
+
+    auto other = any.as_ref();
+
+    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), 2);
+    ASSERT_EQ(other.data(), any.data());
+}
+
+TEST(Any, SBOInPlaceNullptrConstruction) {
+    int *instance = nullptr;
+    entt::any any{std::in_place, instance};
 
     ASSERT_FALSE(any);
     ASSERT_FALSE(any.owner());
     ASSERT_EQ(any.policy(), entt::any_policy::empty);
     ASSERT_EQ(any.type(), entt::type_id<void>());
-    ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
-    ASSERT_EQ(any.data(), nullptr);
 }
 
 TEST(Any, SBOInPlaceTypeConstruction) {
@@ -361,6 +392,37 @@ TEST(Any, SBOAsConstRefTransferValue) {
     ASSERT_EQ(value, 2);
 }
 
+TEST(Any, NoSBOInPlaceConstruction) {
+    std::unique_ptr<fat> instance = std::make_unique<fat>(.1, .2, .3, .4);
+    entt::any any{std::in_place, instance.release()};
+
+    ASSERT_TRUE(any);
+    ASSERT_TRUE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::dynamic);
+    ASSERT_EQ(any.type(), entt::type_id<fat>());
+    ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
+    ASSERT_EQ(entt::any_cast<fat>(any), (fat{.1, .2, .3, .4}));
+
+    auto other = any.as_ref();
+
+    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());
+}
+
+TEST(Any, NoSBOInPlaceNullptrConstruction) {
+    fat *instance = nullptr;
+    entt::any any{std::in_place, instance};
+
+    ASSERT_FALSE(any);
+    ASSERT_FALSE(any.owner());
+    ASSERT_EQ(any.policy(), entt::any_policy::empty);
+    ASSERT_EQ(any.type(), entt::type_id<void>());
+}
+
 TEST(Any, NoSBOInPlaceTypeConstruction) {
     const fat instance{.1, .2, .3, .4};
     entt::any any{std::in_place_type<fat>, instance};