Răsfoiți Sursa

any: make ::initialize fully support void

skypjack 4 luni în urmă
părinte
comite
ebb2af1225
1 a modificat fișierele cu 42 adăugiri și 47 ștergeri
  1. 42 47
      src/entt/core/any.hpp

+ 42 - 47
src/entt/core/any.hpp

@@ -131,48 +131,48 @@ class basic_any: private internal::basic_any_storage<Len, Align> {
 
     template<typename Type, typename... Args>
     void initialize([[maybe_unused]] Args &&...args) {
-        if constexpr(!std::is_void_v<Type>) {
-            using plain_type = std::remove_const_t<std::remove_reference_t<Type>>;
-
-            vtable = basic_vtable<plain_type>;
-            descriptor = &type_id<plain_type>;
+        using plain_type = std::remove_const_t<std::remove_reference_t<Type>>;
+
+        vtable = basic_vtable<plain_type>;
+        descriptor = &type_id<plain_type>;
+
+        if constexpr(std::is_void_v<Type>) {
+            vtable = nullptr;
+            mode = any_policy::empty;
+            this->instance = nullptr;
+        } else 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>> ? any_policy::cref : any_policy::ref;
+            // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
+            this->instance = (std::addressof(args), ...);
+        } else if constexpr(in_situ_v<plain_type>) {
+            mode = any_policy::embedded;
+
+            if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
+                ::new(&this->buffer) plain_type{std::forward<Args>(args)...};
+            } else {
+                // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
+                ::new(&this->buffer) plain_type(std::forward<Args>(args)...);
+            }
+        } else {
+            mode = any_policy::dynamic;
 
-            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>> ? any_policy::cref : any_policy::ref;
-                // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
-                this->instance = (std::addressof(args), ...);
-            } else if constexpr(in_situ_v<plain_type>) {
-                mode = any_policy::embedded;
-
-                if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
-                    ::new(&this->buffer) plain_type{std::forward<Args>(args)...};
-                } else {
-                    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
-                    ::new(&this->buffer) plain_type(std::forward<Args>(args)...);
-                }
+            if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
+                this->instance = new plain_type{std::forward<Args>(args)...};
+            } else if constexpr(std::is_array_v<plain_type>) {
+                static_assert(sizeof...(Args) == 0u, "Invalid arguments");
+                this->instance = new plain_type[std::extent_v<plain_type>]();
             } else {
-                mode = any_policy::dynamic;
-
-                if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) {
-                    this->instance = new plain_type{std::forward<Args>(args)...};
-                } else if constexpr(std::is_array_v<plain_type>) {
-                    static_assert(sizeof...(Args) == 0u, "Invalid arguments");
-                    this->instance = new plain_type[std::extent_v<plain_type>]();
-                } else {
-                    this->instance = new plain_type(std::forward<Args>(args)...);
-                }
+                this->instance = new plain_type(std::forward<Args>(args)...);
             }
         }
     }
 
     basic_any(const basic_any &other, const any_policy pol) noexcept
-        : base_type{},
+        : base_type{other.data()},
           vtable{other.vtable},
           descriptor{other.descriptor},
-          mode{pol} {
-        this->instance = other.data();
-    }
+          mode{pol} {}
 
     void destroy_if_owner() {
         if(owner()) {
@@ -212,7 +212,9 @@ public:
         : base_type{} {
         static_assert(!std::is_const_v<Type> && !std::is_void_v<Type>, "Non-const non-void pointer required");
 
-        if(value != nullptr) {
+        if(value == nullptr) {
+            initialize<void>();
+        } else {
             initialize<Type &>(*value);
             mode = any_policy::dynamic;
         }
@@ -266,11 +268,8 @@ public:
      */
     basic_any &operator=(const basic_any &other) {
         if(this != &other) {
-            reset();
-
-            if(other.vtable) {
-                other.vtable(request::copy, other, this);
-            }
+            destroy_if_owner();
+            other.vtable ? other.vtable(request::copy, other, this) : initialize<void>();
         }
 
         return *this;
@@ -424,7 +423,7 @@ public:
      */
     template<typename Type, typename... Args>
     void emplace(Args &&...args) {
-        reset();
+        destroy_if_owner();
         initialize<Type>(std::forward<Args>(args)...);
     }
 
@@ -460,11 +459,7 @@ public:
     /*! @brief Destroys contained object */
     void reset() {
         destroy_if_owner();
-
-        this->instance = nullptr;
-        vtable = nullptr;
-        descriptor = &type_id<void>;
-        mode = any_policy::empty;
+        initialize<void>();
     }
 
     /**
@@ -528,8 +523,8 @@ public:
 
 private:
     vtable_type *vtable{};
-    const type_info &(*descriptor)() noexcept {&type_id<void>};
-    any_policy mode{any_policy::empty};
+    const type_info &(*descriptor)() noexcept {};
+    any_policy mode{};
 };
 
 /**