This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

View File

@@ -0,0 +1,311 @@
[allocator.uses.construction]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.uses.construction)
### 20.2.8 uses_allocator [[allocator.uses]](allocator.uses#construction)
#### 20.2.8.2 Uses-allocator construction [allocator.uses.construction]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1310)
[*Uses-allocator construction*](#def:uses-allocator_construction "20.2.8.2Uses-allocator construction[allocator.uses.construction]") with allocator alloc and constructor arguments args... refers to the construction of an object of type T such that alloc is passed to the constructor of T if T uses an allocator type compatible with alloc[.](#1.sentence-1)
When applied to the construction of an object of type T,
it is equivalent to initializing it with the value of the expressionmake_obj_using_allocator<T>(alloc, args...), described below[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1320)
The following utility functions support
three conventions for passing alloc to a constructor:
- [(2.1)](#2.1)
If T does not use an allocator compatible with alloc,
then alloc is ignored[.](#2.1.sentence-1)
- [(2.2)](#2.2)
Otherwise, if T has a constructor invocable as T(allocator_arg, alloc, args...) (leading-allocator convention),
then uses-allocator construction chooses this constructor form[.](#2.2.sentence-1)
- [(2.3)](#2.3)
Otherwise, if T has a constructor invocable as T(args..., alloc) (trailing-allocator convention),
then uses-allocator construction chooses this constructor form[.](#2.3.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1337)
The uses_allocator_construction_args function template
takes an allocator and argument list and
produces (as a tuple) a new argument list matching one of the above conventions[.](#3.sentence-1)
Additionally, overloads are provided
that treat specializations of pair such that uses-allocator construction is applied individually
to the first and second data members[.](#3.sentence-2)
The make_obj_using_allocator anduninitialized_construct_using_allocator function templates
apply the modified constructor arguments
to construct an object of type T as a return value or in-place, respectively[.](#3.sentence-3)
[*Note [1](#note-1)*:
For uses_allocator_construction_args andmake_obj_using_allocator, type T is not deduced and must therefore be specified explicitly by the caller[.](#3.sentence-4)
— *end note*]
[🔗](#lib:uses_allocator_construction_args)
`template<class T, class Alloc, class... Args>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
Args&&... args) noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1364)
*Constraints*: remove_cv_t<T> is not a specialization of pair[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1368)
*Returns*: A tuple value determined as follows:
- [(5.1)](#5.1)
If uses_allocator_v<remove_cv_t<T>, Alloc> is false and is_constructible_v<T, Args...> is true,
return forward_as_tuple(std::forward<Args>(args)...)[.](#5.1.sentence-1)
- [(5.2)](#5.2)
Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true and is_constructible_v<T, allocator_arg_t, const Alloc&, Args...> is true,
returntuple<allocator_arg_t, const Alloc&, Args&&...>( allocator_arg, alloc, std::forward<Args>(args)...)
- [(5.3)](#5.3)
Otherwise, if uses_allocator_v<remove_cv_t<T>, Alloc> is true and is_constructible_v<T, Args..., const Alloc&> is true,
return forward_as_tuple(std::forward<Args>(args)..., alloc)[.](#5.3.sentence-1)
- [(5.4)](#5.4)
Otherwise, the program is ill-formed[.](#5.4.sentence-1)
[*Note [2](#note-2)*:
This definition prevents a silent failure
to pass the allocator to a constructor of a type for whichuses_allocator_v<T, Alloc> is true[.](#5.sentence-2)
— *end note*]
[🔗](#lib:uses_allocator_construction_args_)
`template<class T, class Alloc, class Tuple1, class Tuple2>
constexpr auto uses_allocator_construction_args(const Alloc& alloc, piecewise_construct_t,
Tuple1&& x, Tuple2&& y) noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1407)
Let T1 be T::first_type[.](#6.sentence-1)
Let T2 be T::second_type[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1411)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1415)
*Effects*: Equivalent to:return make_tuple( piecewise_construct,
apply([&alloc](auto&&... args1) {return uses_allocator_construction_args<T1>( alloc, std::forward<decltype(args1)>(args1)...); }, std::forward<Tuple1>(x)),
apply([&alloc](auto&&... args2) {return uses_allocator_construction_args<T2>( alloc, std::forward<decltype(args2)>(args2)...); }, std::forward<Tuple2>(y)));
[🔗](#lib:uses_allocator_construction_args__)
`template<class T, class Alloc>
constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept;
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1439)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1443)
*Effects*: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct,
tuple<>{}, tuple<>{});
[🔗](#lib:uses_allocator_construction_args___)
`template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
U&& u, V&& v) noexcept;
`
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1460)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1464)
*Effects*: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct,
forward_as_tuple(std::forward<U>(u)),
forward_as_tuple(std::forward<V>(v)));
[🔗](#lib:uses_allocator_construction_args____)
`template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
pair<U, V>& pr) noexcept;
template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
const pair<U, V>& pr) noexcept;
`
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1485)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1489)
*Effects*: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct,
forward_as_tuple(pr.first),
forward_as_tuple(pr.second));
[🔗](#lib:uses_allocator_construction_args_____)
`template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
pair<U, V>&& pr) noexcept;
template<class T, class Alloc, class U, class V>
constexpr auto uses_allocator_construction_args(const Alloc& alloc,
const pair<U, V>&& pr) noexcept;
`
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1510)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1514)
*Effects*: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct,
forward_as_tuple(get<0>(std::move(pr))),
forward_as_tuple(get<1>(std::move(pr))));
[🔗](#lib:uses_allocator_construction_args______)
`template<class T, class Alloc, [pair-like](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") P>
constexpr auto uses_allocator_construction_args(const Alloc& alloc, P&& p) noexcept;
`
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1531)
*Constraints*: remove_cv_t<T> is a specialization of pair andremove_cvref_t<P> is not a specialization of ranges::subrange[.](#17.sentence-1)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1536)
*Effects*: Equivalent to:return uses_allocator_construction_args<T>(alloc, piecewise_construct,
forward_as_tuple(get<0>(std::forward<P>(p))),
forward_as_tuple(get<1>(std::forward<P>(p))));
[🔗](#lib:uses_allocator_construction_args_______)
`template<class T, class Alloc, class U>
constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u) noexcept;
`
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1553)
Let *FUN* be the function template:template<class A, class B>void *FUN*(const pair<A, B>&);
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1560)
*Constraints*: remove_cv_t<T> is a specialization of pair, and either:
- [(20.1)](#20.1)
remove_cvref_t<U> is a specialization of ranges::subrange, or
- [(20.2)](#20.2)
U does not satisfy [*pair-like*](tuple.syn#concept:pair-like "22.4.2Header <tuple> synopsis[tuple.syn]") and
the expression *FUN*(u) is not well-formed
when considered as an unevaluated operand[.](#20.sentence-1)
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1572)
Let *pair-constructor* be an exposition-only class defined as follows:class *pair-constructor* {using *pair-type* = remove_cv_t<T>; // *exposition only*constexpr auto *do-construct*(const *pair-type*& p) const { // *exposition only*return make_obj_using_allocator<*pair-type*>(*alloc_*, p); }constexpr auto *do-construct*(*pair-type*&& p) const { // *exposition only*return make_obj_using_allocator<*pair-type*>(*alloc_*, std::move(p)); }const Alloc& *alloc_*; // *exposition only* U& *u_*; // *exposition only*public:constexpr operator *pair-type*() const {return *do-construct*(std::forward<U>(*u_*)); }};
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1595)
*Returns*: make_tuple(pc),
where pc is a *pair-constructor* object
whose *alloc_* member is initialized with alloc and
whose *u_* member is initialized with u[.](#22.sentence-1)
[🔗](#lib:make_obj_using_allocator)
`template<class T, class Alloc, class... Args>
constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args);
`
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1610)
*Effects*: Equivalent to:return make_from_tuple<T>(uses_allocator_construction_args<T>( alloc, std::forward<Args>(args)...));
[🔗](#lib:uninitialized_construct_using_allocator)
`template<class T, class Alloc, class... Args>
constexpr T* uninitialized_construct_using_allocator(T* p, const Alloc& alloc, Args&&... args);
`
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1626)
*Effects*: Equivalent to:return apply([&]<class... U>(U&&... xs) {return construct_at(p, std::forward<U>(xs)...); }, uses_allocator_construction_args<T>(alloc, std::forward<Args>(args)...));

View File

@@ -0,0 +1,39 @@
[allocator.uses.trait]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.uses.trait)
### 20.2.8 uses_allocator [[allocator.uses]](allocator.uses#trait)
#### 20.2.8.1 uses_allocator trait [allocator.uses.trait]
[🔗](#lib:uses_allocator)
`template<class T, class Alloc> struct uses_allocator;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1288)
*Remarks*: Automatically detects whether T has a nested allocator_type that
is convertible from Alloc[.](#1.sentence-1)
Meets the [*Cpp17BinaryTypeTrait*](meta.rqmts#:Cpp17BinaryTypeTrait "21.3.2Requirements[meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2Requirements"))[.](#1.sentence-2)
The implementation shall provide a definition that is
derived from true_type if the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") T::allocator_type is valid and denotes a type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")) andis_convertible_v<Alloc, T::allocator_type> != false, otherwise it shall be
derived from false_type[.](#1.sentence-3)
A program may specialize this template to derive fromtrue_type for a program-defined type T that does not have a nestedallocator_type but nonetheless can be constructed with an allocator where
either:
- [(1.1)](#1.1)
the first argument of a constructor has type allocator_arg_t and the
second argument has type Alloc or
- [(1.2)](#1.2)
the last argument of a constructor has type Alloc[.](#1.sentence-4)