Selaa lähdekoodia

any: make_any

Michele Caini 4 vuotta sitten
vanhempi
commit
3d6202ecfd
4 muutettua tiedostoa jossa 61 lisäystä ja 9 poistoa
  1. 12 3
      docs/md/core.md
  2. 24 4
      src/entt/core/any.hpp
  3. 2 2
      src/entt/core/fwd.hpp
  4. 23 0
      test/entt/core/any.cpp

+ 12 - 3
docs/md/core.md

@@ -247,8 +247,16 @@ entt::any any{0};
 entt::any in_place{std::in_place_type<int>, 42};
 entt::any in_place{std::in_place_type<int>, 42};
 ```
 ```
 
 
-The `any` class takes the burden of destroying the contained element when
-required, regardless of the storage strategy used for the specific object.<br/>
+Alternatively, the `make_any` function serves the same purpose but requires to
+always be explicit about the type:
+
+```cpp
+entt::any any = entt::make_any<int>(42);
+```
+
+In both cases, the `any` class takes the burden of destroying the contained
+element when required, regardless of the storage strategy used for the specific
+object.<br/>
 Furthermore, an instance of `any` is not tied to an actual type. Therefore, the
 Furthermore, an instance of `any` is not tied to an actual type. Therefore, the
 wrapper will be reconfigured by assigning it an object of a different type than
 wrapper will be reconfigured by assigning it an object of a different type than
 the one contained, so as to be able to handle the new instance.<br/>
 the one contained, so as to be able to handle the new instance.<br/>
@@ -278,7 +286,8 @@ entt::any cany{std::cref(value)};
 
 
 // alias construction
 // alias construction
 int value = 42;
 int value = 42;
-entt::any in_place{std::in_place_type<int &>, &value};
+entt::any in_place{std::in_place_type<int &>, value};
+entt::any make_any = entt::make_any<int &>(value);
 ```
 ```
 
 
 In other words, whenever `any` intercepts a `reference_wrapper` or is explicitly
 In other words, whenever `any` intercepts a `reference_wrapper` or is explicitly

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

@@ -154,6 +154,11 @@ class basic_any {
     }
     }
 
 
 public:
 public:
+    /*! @brief Size of the internal storage. */
+    static constexpr auto length = Len;
+    /*! @brief Alignment requirement. */
+    static constexpr auto alignment = Align;
+
     /*! @brief Default constructor. */
     /*! @brief Default constructor. */
     basic_any() ENTT_NOEXCEPT
     basic_any() ENTT_NOEXCEPT
         : instance{},
         : instance{},
@@ -161,7 +166,7 @@ public:
     {}
     {}
 
 
     /**
     /**
-     * @brief Constructs an any by directly initializing the new object.
+     * @brief Constructs a wrapper by directly initializing the new object.
      * @tparam Type Type of object to use to initialize the wrapper.
      * @tparam Type Type of object to use to initialize the wrapper.
      * @tparam Args Types of arguments to use to construct the new instance.
      * @tparam Args Types of arguments to use to construct the new instance.
      * @param args Parameters to use to construct the instance.
      * @param args Parameters to use to construct the instance.
@@ -175,7 +180,7 @@ public:
     }
     }
 
 
     /**
     /**
-     * @brief Constructs an any that holds an unmanaged object.
+     * @brief Constructs a wrapper that holds an unmanaged object.
      * @tparam Type Type of object to use to initialize the wrapper.
      * @tparam Type Type of object to use to initialize the wrapper.
      * @param value An instance of an object to use to initialize the wrapper.
      * @param value An instance of an object to use to initialize the wrapper.
      */
      */
@@ -188,7 +193,7 @@ public:
     }
     }
 
 
     /**
     /**
-     * @brief Constructs an any from a given value.
+     * @brief Constructs a wrapper from a given value.
      * @tparam Type Type of object to use to initialize the wrapper.
      * @tparam Type Type of object to use to initialize the wrapper.
      * @param value An instance of an object to use to initialize the wrapper.
      * @param value An instance of an object to use to initialize the wrapper.
      */
      */
@@ -334,7 +339,7 @@ public:
 
 
     /**
     /**
      * @brief Aliasing constructor.
      * @brief Aliasing constructor.
-     * @return An any that shares a reference to an unmanaged object.
+     * @return A wrapper that shares a reference to an unmanaged object.
      */
      */
     [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
     [[nodiscard]] basic_any as_ref() ENTT_NOEXCEPT {
         basic_any ref{};
         basic_any ref{};
@@ -420,6 +425,21 @@ Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
 }
 }
 
 
 
 
+/**
+ * @brief Constructs a wrapper from a given type, passing it all arguments.
+ * @tparam Type Type of object to use to initialize the wrapper.
+ * @tparam Len Size of the storage reserved for the small buffer optimization.
+ * @tparam Align Optional alignment requirement.
+ * @tparam Args Types of arguments to use to construct the new instance.
+ * @param args Parameters to use to construct the instance.
+ * @return A properly initialized wrapper for an object of the given type.
+ */
+template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args>
+basic_any<Len, Align> make_any(Args &&... args) {
+    return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...};
+}
+
+
 }
 }
 
 
 
 

+ 2 - 2
src/entt/core/fwd.hpp

@@ -9,7 +9,7 @@
 namespace entt {
 namespace entt {
 
 
 
 
-template<std::size_t Len, std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
+template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
 class basic_any;
 class basic_any;
 
 
 
 
@@ -18,7 +18,7 @@ using id_type = ENTT_ID_TYPE;
 
 
 
 
 /*! @brief Alias declaration for the most common use case. */
 /*! @brief Alias declaration for the most common use case. */
-using any = basic_any<sizeof(double[2])>;
+using any = basic_any<>;
 
 
 
 
 }
 }

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

@@ -857,6 +857,29 @@ TEST_F(Any, AnyCast) {
     ASSERT_DEATH(entt::any_cast<double>(entt::any{42}), "");
     ASSERT_DEATH(entt::any_cast<double>(entt::any{42}), "");
 }
 }
 
 
+TEST_F(Any, MakeAny) {
+    int value = 42;
+    auto any = entt::make_any<int>(value);
+    auto ext = entt::make_any<int, sizeof(int), alignof(int)>(value);
+    auto ref = entt::make_any<int &>(value);
+
+    ASSERT_TRUE(any);
+    ASSERT_TRUE(ext);
+    ASSERT_TRUE(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);
+
+    ASSERT_EQ(decltype(any)::length, entt::any::length);
+    ASSERT_NE(decltype(ext)::length, entt::any::length);
+    ASSERT_EQ(decltype(ref)::length, entt::any::length);
+
+    ASSERT_NE(any.data(), &value);
+    ASSERT_NE(ext.data(), &value);
+    ASSERT_EQ(ref.data(), &value);
+}
+
 TEST_F(Any, NotCopyableType) {
 TEST_F(Any, NotCopyableType) {
     auto test = [](entt::any any) {
     auto test = [](entt::any any) {
         entt::any copy{any};
         entt::any copy{any};