From 3d6202ecfd3bd8a210bbe94aafaff4dc2861a0b2 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Sun, 25 Apr 2021 16:15:18 +0200 Subject: [PATCH] any: make_any --- docs/md/core.md | 15 ++++++++++++--- src/entt/core/any.hpp | 28 ++++++++++++++++++++++++---- src/entt/core/fwd.hpp | 4 ++-- test/entt/core/any.cpp | 23 +++++++++++++++++++++++ 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/docs/md/core.md b/docs/md/core.md index 51c786328..ecd214b92 100644 --- a/docs/md/core.md +++ b/docs/md/core.md @@ -247,8 +247,16 @@ entt::any any{0}; entt::any in_place{std::in_place_type, 42}; ``` -The `any` class takes the burden of destroying the contained element when -required, regardless of the storage strategy used for the specific object.
+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(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.
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 the one contained, so as to be able to handle the new instance.
@@ -278,7 +286,8 @@ entt::any cany{std::cref(value)}; // alias construction int value = 42; -entt::any in_place{std::in_place_type, &value}; +entt::any in_place{std::in_place_type, value}; +entt::any make_any = entt::make_any(value); ``` In other words, whenever `any` intercepts a `reference_wrapper` or is explicitly diff --git a/src/entt/core/any.hpp b/src/entt/core/any.hpp index d3b7154d6..40ed50915 100644 --- a/src/entt/core/any.hpp +++ b/src/entt/core/any.hpp @@ -154,6 +154,11 @@ class basic_any { } public: + /*! @brief Size of the internal storage. */ + static constexpr auto length = Len; + /*! @brief Alignment requirement. */ + static constexpr auto alignment = Align; + /*! @brief Default constructor. */ basic_any() ENTT_NOEXCEPT : 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 Args Types of arguments to use to construct the new 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. * @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. * @param value An instance of an object to use to initialize the wrapper. */ @@ -334,7 +339,7 @@ public: /** * @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 { basic_any ref{}; @@ -420,6 +425,21 @@ Type * any_cast(basic_any *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::length, std::size_t Align = basic_any::alignment, typename... Args> +basic_any make_any(Args &&... args) { + return basic_any{std::in_place_type, std::forward(args)...}; +} + + } diff --git a/src/entt/core/fwd.hpp b/src/entt/core/fwd.hpp index da297ea19..193aad86a 100644 --- a/src/entt/core/fwd.hpp +++ b/src/entt/core/fwd.hpp @@ -9,7 +9,7 @@ namespace entt { -template)> +template)> class basic_any; @@ -18,7 +18,7 @@ using id_type = ENTT_ID_TYPE; /*! @brief Alias declaration for the most common use case. */ -using any = basic_any; +using any = basic_any<>; } diff --git a/test/entt/core/any.cpp b/test/entt/core/any.cpp index 4d6f0e2bd..74d01e6d1 100644 --- a/test/entt/core/any.cpp +++ b/test/entt/core/any.cpp @@ -857,6 +857,29 @@ TEST_F(Any, AnyCast) { ASSERT_DEATH(entt::any_cast(entt::any{42}), ""); } +TEST_F(Any, MakeAny) { + int value = 42; + auto any = entt::make_any(value); + auto ext = entt::make_any(value); + auto ref = entt::make_any(value); + + ASSERT_TRUE(any); + ASSERT_TRUE(ext); + ASSERT_TRUE(ref); + + ASSERT_EQ(entt::any_cast(any), 42); + ASSERT_EQ(entt::any_cast(ext), 42); + ASSERT_EQ(entt::any_cast(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) { auto test = [](entt::any any) { entt::any copy{any};