1#ifndef ENTT_CORE_MEMORY_HPP
2#define ENTT_CORE_MEMORY_HPP
9#include "../config/config.h"
19template<
typename Type>
21 if constexpr(std::is_pointer_v<std::decay_t<Type>>) {
34template<
typename Allocator>
36 if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
47template<
typename Allocator>
49 if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
60template<
typename Allocator>
62 if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
66 ENTT_ASSERT_CONSTEXPR(
lhs ==
rhs,
"Cannot swap the containers");
74template<
typename Allocator>
79 using pointer =
typename std::allocator_traits<Allocator>::pointer;
92 constexpr void operator()(
pointer ptr)
noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) {
93 using alloc_traits = std::allocator_traits<Allocator>;
95 alloc_traits::deallocate(*
this,
ptr, 1u);
108template<
typename Type,
typename Allocator,
typename...
Args>
110 static_assert(!std::is_array_v<Type>,
"Array types are not supported");
112 using alloc_traits =
typename std::allocator_traits<Allocator>::template
rebind_traits<Type>;
113 using allocator_type =
typename alloc_traits::allocator_type;
116 auto ptr = alloc_traits::allocate(
alloc, 1u);
122 alloc_traits::deallocate(
alloc,
ptr, 1u);
126 return std::unique_ptr<Type, allocation_deleter<allocator_type>>{
ptr,
alloc};
132template<
typename Type>
133struct uses_allocator_construction {
134 template<
typename Allocator,
typename... Params>
135 static constexpr auto args([[maybe_unused]]
const Allocator &allocator, Params &&...params)
noexcept {
136 if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) {
137 return std::forward_as_tuple(std::forward<Params>(params)...);
139 static_assert(std::uses_allocator_v<Type, Allocator>,
"Ill-formed request");
141 if constexpr(std::is_constructible_v<Type, std::allocator_arg_t,
const Allocator &, Params...>) {
142 return std::tuple<std::allocator_arg_t,
const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...};
144 static_assert(std::is_constructible_v<Type, Params...,
const Allocator &>,
"Ill-formed request");
145 return std::forward_as_tuple(std::forward<Params>(params)..., allocator);
151template<
typename Type,
typename Other>
152struct uses_allocator_construction<std::pair<Type, Other>> {
153 using type = std::pair<Type, Other>;
155 template<
typename Allocator,
typename First,
typename Second>
156 static constexpr auto args(
const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second)
noexcept {
157 return std::make_tuple(
158 std::piecewise_construct,
159 std::apply([&allocator](
auto &&...curr) {
return uses_allocator_construction<Type>::args(allocator, std::forward<
decltype(curr)>(curr)...); }, std::forward<First>(first)),
160 std::apply([&allocator](
auto &&...curr) {
return uses_allocator_construction<Other>::args(allocator, std::forward<
decltype(curr)>(curr)...); }, std::forward<Second>(second)));
163 template<
typename Allocator>
164 static constexpr auto args(
const Allocator &allocator)
noexcept {
165 return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
168 template<
typename Allocator,
typename First,
typename Second>
169 static constexpr auto args(
const Allocator &allocator, First &&first, Second &&second)
noexcept {
170 return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second)));
173 template<
typename Allocator,
typename First,
typename Second>
174 static constexpr auto args(
const Allocator &allocator,
const std::pair<First, Second> &value)
noexcept {
175 return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second));
178 template<
typename Allocator,
typename First,
typename Second>
179 static constexpr auto args(
const Allocator &allocator, std::pair<First, Second> &&value)
noexcept {
180 return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second)));
200template<
typename Type,
typename Allocator,
typename...
Args>
202 return internal::uses_allocator_construction<Type>::args(
allocator, std::forward<Args>(
args)...);
218template<
typename Type,
typename Allocator,
typename...
Args>
220 return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(
allocator, std::forward<Args>(
args)...));
237template<
typename Type,
typename Allocator,
typename...
Args>
239 return std::apply([value](
auto &&...
curr) { return ::new(value) Type(std::forward<
decltype(
curr)>(
curr)...); }, internal::uses_allocator_construction<Type>::args(
allocator, std::forward<Args>(
args)...));
constexpr void propagate_on_container_swap(Allocator &lhs, Allocator &rhs) noexcept
Utility function to design allocation-aware containers.
constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
constexpr void propagate_on_container_move_assignment(Allocator &lhs, Allocator &rhs) noexcept
Utility function to design allocation-aware containers.
constexpr Type * uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args)
Uses-allocator construction utility (waiting for C++20).
constexpr void swap(compressed_pair< First, Second > &lhs, compressed_pair< First, Second > &rhs)
Swaps two compressed pair objects.
constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept
Uses-allocator construction utility (waiting for C++20).
constexpr auto allocate_unique(Allocator &allocator, Args &&...args)
Allows std::unique_ptr to use allocators (waiting for C++20).
constexpr void propagate_on_container_copy_assignment(Allocator &lhs, Allocator &rhs) noexcept
Utility function to design allocation-aware containers.
constexpr auto to_address(Type &&ptr) noexcept
Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
Deleter for allocator-aware unique pointers (waiting for C++20).
typename std::allocator_traits< Allocator >::pointer pointer
Pointer type.
constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v< allocator_type >)
Inherited constructors.
constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v< typename allocator_type::value_type >)
Destroys the pointed object and deallocates its memory.
Allocator allocator_type
Allocator type.