any: make_any

This commit is contained in:
Michele Caini
2021-04-25 16:15:18 +02:00
parent c40f0ef2bb
commit 3d6202ecfd
4 changed files with 61 additions and 9 deletions

View File

@@ -247,8 +247,16 @@ entt::any any{0};
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
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/>
@@ -278,7 +286,8 @@ entt::any cany{std::cref(value)};
// alias construction
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

View File

@@ -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<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)...};
}
}

View File

@@ -9,7 +9,7 @@
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;
@@ -18,7 +18,7 @@ using id_type = ENTT_ID_TYPE;
/*! @brief Alias declaration for the most common use case. */
using any = basic_any<sizeof(double[2])>;
using any = basic_any<>;
}

View File

@@ -857,6 +857,29 @@ TEST_F(Any, AnyCast) {
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) {
auto test = [](entt::any any) {
entt::any copy{any};