memory: uses_allocator_construction_args (waiting for C++20)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "../config/config.h"
|
||||
@@ -162,6 +163,35 @@ auto allocate_unique(Allocator &allocator, Args &&...args) {
|
||||
return std::unique_ptr<Type, allocation_deleter<alloc>>{ptr, type_allocator};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uses-allocator construction utility.
|
||||
*
|
||||
* Primarily intended for internal use. Unlike the standard version (waiting for
|
||||
* C++20), this utility does not differentiate between pair and non-pair types.
|
||||
*
|
||||
* @tparam Type Type to return arguments for.
|
||||
* @tparam Allocator Type of allocator used to manage memory and elements.
|
||||
* @tparam Args Types of arguments to use to construct the object.
|
||||
* @param allocator The allocator to use.
|
||||
* @param args Parameters to use to construct the object.
|
||||
* @return The arguments needed to create an object of the given type.
|
||||
*/
|
||||
template<typename Type, typename Allocator, typename... Args>
|
||||
constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) ENTT_NOEXCEPT {
|
||||
if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Args...>) {
|
||||
return std::forward_as_tuple(std::forward<Args>(args)...);
|
||||
} else {
|
||||
static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request");
|
||||
|
||||
if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Args...>) {
|
||||
return std::tuple<std::allocator_arg_t, const Allocator &, Args &&...>(std::allocator_arg, allocator, std::forward<Args>(args)...);
|
||||
} else {
|
||||
static_assert(std::is_constructible_v<Type, Args..., const Allocator &>, "Ill-formed request");
|
||||
return std::forward_as_tuple(std::forward<Args>(args)..., allocator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace entt
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/memory.hpp>
|
||||
#include "../common/basic_test_allocator.hpp"
|
||||
@@ -115,3 +117,31 @@ TEST(AllocateUnique, UsesAllocatorConstruction) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(UsesAllocatorConstructionArgs, NoUsesAllocatorConstruction) {
|
||||
const auto args = entt::uses_allocator_construction_args<int>(std::allocator<int>{}, 42);
|
||||
|
||||
static_assert(std::tuple_size_v<decltype(args)> == 1u);
|
||||
static_assert(std::is_same_v<decltype(args), const std::tuple<int &&>>);
|
||||
|
||||
ASSERT_EQ(std::get<0>(args), 42);
|
||||
}
|
||||
|
||||
TEST(UsesAllocatorConstructionArgs, LeadingAllocatorConvetion) {
|
||||
const auto args = entt::uses_allocator_construction_args<std::tuple<int, char>>(std::allocator<int>{}, 42, 'c');
|
||||
|
||||
static_assert(std::tuple_size_v<decltype(args)> == 4u);
|
||||
static_assert(std::is_same_v<decltype(args), const std::tuple<std::allocator_arg_t, const std::allocator<int> &, int &&, char &&>>);
|
||||
|
||||
ASSERT_EQ(std::get<2>(args), 42);
|
||||
ASSERT_EQ(std::get<3>(args), 'c');
|
||||
}
|
||||
|
||||
TEST(UsesAllocatorConstructionArgs, TrailingAllocatorConvetion) {
|
||||
const auto args = entt::uses_allocator_construction_args<std::vector<int>>(std::allocator<int>{}, 42);
|
||||
|
||||
static_assert(std::tuple_size_v<decltype(args)> == 2u);
|
||||
static_assert(std::is_same_v<decltype(args), const std::tuple<int &&, const std::allocator<int> &>>);
|
||||
|
||||
ASSERT_EQ(std::get<0>(args), 42);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user