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,380 @@
[allocator.adaptor]
# 20 Memory management library [[mem]](./#mem)
## 20.6 Class template scoped_allocator_adaptor [allocator.adaptor]
### [20.6.1](#syn) Header <scoped_allocator> synopsis [[allocator.adaptor.syn]](allocator.adaptor.syn)
[🔗](#header:%3cscoped_allocator%3e)
namespace std {// class template scoped_allocator_adaptortemplate<class OuterAlloc, class... InnerAlloc>class scoped_allocator_adaptor; // [[scoped.adaptor.operators]](#scoped.adaptor.operators "20.6.5Operators"), scoped allocator operatorstemplate<class OuterA1, class OuterA2, class... InnerAllocs>bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;}
[1](#syn-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8608)
The class template scoped_allocator_adaptor is an allocator template that
specifies an allocator resource (the outer allocator) to be used by a container (as any
other allocator does) and also specifies an inner allocator resource to be passed to the
constructor of every element within the container[.](#syn-1.sentence-1)
This adaptor is instantiated with one
outer and zero or more inner allocator types[.](#syn-1.sentence-2)
If instantiated with only one allocator
type, the inner allocator becomes the scoped_allocator_adaptor itself, thus
using the same allocator resource for the container and every element within the
container and, if the elements themselves are containers, each of their elements
recursively[.](#syn-1.sentence-3)
If instantiated with more than one allocator, the first allocator is the
outer allocator for use by the container, the second allocator is passed to the
constructors of the container's elements, and, if the elements themselves are
containers, the third allocator is passed to the elements' elements, and so on[.](#syn-1.sentence-4)
If
containers are nested to a depth greater than the number of allocators, the last
allocator is used repeatedly, as in the single-allocator case, for any remaining
recursions[.](#syn-1.sentence-5)
[*Note [1](#syn-note-1)*:
The scoped_allocator_adaptor is derived from the outer
allocator type so it can be substituted for the outer allocator type in most
expressions[.](#syn-1.sentence-6)
— *end note*]
[🔗](#lib:scoped_allocator_adaptor)
namespace std {template<class OuterAlloc, class... InnerAllocs>class scoped_allocator_adaptor : public OuterAlloc {private:using OuterTraits = allocator_traits<OuterAlloc>; // *exposition only* scoped_allocator_adaptor<InnerAllocs...> inner; // *exposition only*public:using outer_allocator_type = OuterAlloc; using inner_allocator_type = *see below*; using value_type = typename OuterTraits::value_type; using size_type = typename OuterTraits::size_type; using difference_type = typename OuterTraits::difference_type; using pointer = typename OuterTraits::pointer; using const_pointer = typename OuterTraits::const_pointer; using void_pointer = typename OuterTraits::void_pointer; using const_void_pointer = typename OuterTraits::const_void_pointer; using propagate_on_container_copy_assignment = *see below*; using propagate_on_container_move_assignment = *see below*; using propagate_on_container_swap = *see below*; using is_always_equal = *see below*; template<class Tp> struct rebind {using other = scoped_allocator_adaptor< OuterTraits::template rebind_alloc<Tp>, InnerAllocs...>; };
scoped_allocator_adaptor(); template<class OuterA2> scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;
scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; template<class OuterA2> scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept; template<class OuterA2> scoped_allocator_adaptor( scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; ~scoped_allocator_adaptor();
inner_allocator_type& inner_allocator() noexcept; const inner_allocator_type& inner_allocator() const noexcept;
outer_allocator_type& outer_allocator() noexcept; const outer_allocator_type& outer_allocator() const noexcept;
pointer allocate(size_type n);
pointer allocate(size_type n, const_void_pointer hint); void deallocate(pointer p, size_type n);
size_type max_size() const; template<class T, class... Args>void construct(T* p, Args&&... args); template<class T>void destroy(T* p);
scoped_allocator_adaptor select_on_container_copy_construction() const; }; template<class OuterAlloc, class... InnerAllocs> scoped_allocator_adaptor(OuterAlloc, InnerAllocs...)-> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;}
### [20.6.2](#types) Member types [[allocator.adaptor.types]](allocator.adaptor.types)
[🔗](#lib:inner_allocator_type,scoped_allocator_adaptor)
`using inner_allocator_type = see below;
`
[1](#types-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8722)
*Type*: scoped_allocator_adaptor<OuterAlloc> if sizeof...(InnerAllocs) is
zero; otherwise,
scoped_allocator_adaptor<InnerAllocs...>[.](#types-1.sentence-2)
[🔗](#lib:propagate_on_container_copy_assignment,scoped_allocator_adaptor)
`using propagate_on_container_copy_assignment = see below;
`
[2](#types-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8733)
*Type*: true_type ifallocator_traits<A>::propagate_on_container_copy_assignment::value istrue for any A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#types-2.sentence-1)
[🔗](#lib:propagate_on_container_move_assignment,scoped_allocator_adaptor)
`using propagate_on_container_move_assignment = see below;
`
[3](#types-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8746)
*Type*: true_type ifallocator_traits<A>::propagate_on_container_move_assignment::value istrue for any A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#types-3.sentence-1)
[🔗](#lib:propagate_on_container_swap,scoped_allocator_adaptor)
`using propagate_on_container_swap = see below;
`
[4](#types-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8759)
*Type*: true_type ifallocator_traits<A>::propagate_on_container_swap::value istrue for any A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#types-4.sentence-1)
[🔗](#lib:is_always_equal,scoped_allocator_adaptor)
`using is_always_equal = see below;
`
[5](#types-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8772)
*Type*: true_type ifallocator_traits<A>::is_always_equal::value istrue for every A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#types-5.sentence-1)
### [20.6.3](#cnstr) Constructors [[allocator.adaptor.cnstr]](allocator.adaptor.cnstr)
[🔗](#lib:scoped_allocator_adaptor,constructor)
`scoped_allocator_adaptor();
`
[1](#cnstr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8787)
*Effects*: Value-initializes the OuterAlloc base class and the inner allocator
object[.](#cnstr-1.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor_)
`template<class OuterA2>
scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;
`
[2](#cnstr-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8800)
*Constraints*: is_constructible_v<OuterAlloc, OuterA2> is true[.](#cnstr-2.sentence-1)
[3](#cnstr-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8804)
*Effects*: Initializes the OuterAlloc base class withstd::forward<OuterA2>(outerAlloc) and inner with innerAllocs... (hence recursively initializing each allocator within the adaptor with the corresponding
allocator from the argument list)[.](#cnstr-3.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor__)
`scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
`
[4](#cnstr-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8818)
*Effects*: Initializes each allocator within the adaptor with the corresponding allocator
from other[.](#cnstr-4.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor___)
`scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
`
[5](#cnstr-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8830)
*Effects*: Move constructs each allocator within the adaptor with the corresponding allocator
from other[.](#cnstr-5.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor____)
`template<class OuterA2>
scoped_allocator_adaptor(
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
`
[6](#cnstr-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8844)
*Constraints*: is_constructible_v<OuterAlloc, const OuterA2&> is true[.](#cnstr-6.sentence-1)
[7](#cnstr-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8848)
*Effects*: Initializes each allocator within the adaptor with the corresponding allocator
from other[.](#cnstr-7.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor_____)
`template<class OuterA2>
scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
`
[8](#cnstr-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8861)
*Constraints*: is_constructible_v<OuterAlloc, OuterA2> is true[.](#cnstr-8.sentence-1)
[9](#cnstr-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8865)
*Effects*: Initializes each allocator within the adaptor with the corresponding allocator rvalue
from other[.](#cnstr-9.sentence-1)
### [20.6.4](#members) Members [[allocator.adaptor.members]](allocator.adaptor.members)
[1](#members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8873)
In the construct member functions,*OUTERMOST*(x) is*OUTERMOST*(x.outer_allocator()) if
the expression x.outer_allocator() is
valid ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")) andx otherwise;*OUTERMOST_ALLOC_TRAITS*(x) isallocator_traits<remove_reference_t<decltype(*OUTERMOST*(x))>>[.](#members-1.sentence-1)
[*Note [1](#members-note-1)*:
*OUTERMOST*(x) and*OUTERMOST_ALLOC_TRAITS*(x) are recursive operations[.](#members-1.sentence-2)
It
is incumbent upon the definition of outer_allocator() to ensure that the
recursion terminates[.](#members-1.sentence-3)
It will terminate for all instantiations ofscoped_allocator_adaptor[.](#members-1.sentence-4)
— *end note*]
[🔗](#lib:inner_allocator,scoped_allocator_adaptor)
`inner_allocator_type& inner_allocator() noexcept;
const inner_allocator_type& inner_allocator() const noexcept;
`
[2](#members-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8897)
*Returns*: *this if sizeof...(InnerAllocs) is zero; otherwise,inner[.](#members-2.sentence-1)
[🔗](#lib:outer_allocator,scoped_allocator_adaptor)
`outer_allocator_type& outer_allocator() noexcept;
`
[3](#members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8909)
*Returns*: static_cast<OuterAlloc&>(*this)[.](#members-3.sentence-1)
[🔗](#lib:outer_allocator,scoped_allocator_adaptor_)
`const outer_allocator_type& outer_allocator() const noexcept;
`
[4](#members-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8920)
*Returns*: static_cast<const OuterAlloc&>(*this)[.](#members-4.sentence-1)
[🔗](#lib:allocate,scoped_allocator_adaptor)
`pointer allocate(size_type n);
`
[5](#members-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8931)
*Returns*: allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)[.](#members-5.sentence-1)
[🔗](#lib:allocate,scoped_allocator_adaptor_)
`pointer allocate(size_type n, const_void_pointer hint);
`
[6](#members-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8942)
*Returns*: allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)[.](#members-6.sentence-1)
[🔗](#lib:deallocate,scoped_allocator_adaptor)
`void deallocate(pointer p, size_type n) noexcept;
`
[7](#members-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8953)
*Effects*: As if by:allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n);
[🔗](#lib:max_size,scoped_allocator_adaptor)
`size_type max_size() const;
`
[8](#members-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8965)
*Returns*: allocator_traits<OuterAlloc>::max_size(outer_allocator())[.](#members-8.sentence-1)
[🔗](#lib:construct,scoped_allocator_adaptor)
`template<class T, class... Args>
void construct(T* p, Args&&... args);
`
[9](#members-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8977)
*Effects*: Equivalent to:apply([p, this](auto&&... newargs) {*OUTERMOST_ALLOC_TRAITS*(*this)::construct(*OUTERMOST*(*this), p,
std::forward<decltype(newargs)>(newargs)...); },
uses_allocator_construction_args<T>(inner_allocator(),
std::forward<Args>(args)...));
[🔗](#lib:destroy,scoped_allocator_adaptor)
`template<class T>
void destroy(T* p);
`
[10](#members-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8998)
*Effects*: Calls *OUTERMOST_ALLOC_TRAITS*(*this)::destroy(*OUTERMOST*(*this), p)[.](#members-10.sentence-1)
[🔗](#lib:select_on_container_copy_construction,scoped_allocator_adaptor)
`scoped_allocator_adaptor select_on_container_copy_construction() const;
`
[11](#members-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L9009)
*Returns*: A new scoped_allocator_adaptor object
where each allocator a1 within the adaptor
is initialized withallocator_traits<A1>::select_on_container_copy_construction(a2),
where A1 is the type of a1 anda2 is the corresponding allocator in *this[.](#members-11.sentence-1)
### [20.6.5](#scoped.adaptor.operators) Operators [[scoped.adaptor.operators]](scoped.adaptor.operators)
[🔗](#lib:operator==,scoped_allocator_adaptor)
`template<class OuterA1, class OuterA2, class... InnerAllocs>
bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
`
[1](#scoped.adaptor.operators-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L9029)
*Returns*: If sizeof...(InnerAllocs) is zero,a.outer_allocator() == b.outer_allocator() otherwisea.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator()

View File

@@ -0,0 +1,101 @@
[allocator.adaptor.cnstr]
# 20 Memory management library [[mem]](./#mem)
## 20.6 Class template scoped_allocator_adaptor [[allocator.adaptor]](allocator.adaptor#cnstr)
### 20.6.3 Constructors [allocator.adaptor.cnstr]
[🔗](#lib:scoped_allocator_adaptor,constructor)
`scoped_allocator_adaptor();
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8787)
*Effects*: Value-initializes the OuterAlloc base class and the inner allocator
object[.](#1.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor_)
`template<class OuterA2>
scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8800)
*Constraints*: is_constructible_v<OuterAlloc, OuterA2> is true[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8804)
*Effects*: Initializes the OuterAlloc base class withstd::forward<OuterA2>(outerAlloc) and inner with innerAllocs... (hence recursively initializing each allocator within the adaptor with the corresponding
allocator from the argument list)[.](#3.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor__)
`scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8818)
*Effects*: Initializes each allocator within the adaptor with the corresponding allocator
from other[.](#4.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor___)
`scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8830)
*Effects*: Move constructs each allocator within the adaptor with the corresponding allocator
from other[.](#5.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor____)
`template<class OuterA2>
scoped_allocator_adaptor(
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8844)
*Constraints*: is_constructible_v<OuterAlloc, const OuterA2&> is true[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8848)
*Effects*: Initializes each allocator within the adaptor with the corresponding allocator
from other[.](#7.sentence-1)
[🔗](#lib:scoped_allocator_adaptor,constructor_____)
`template<class OuterA2>
scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8861)
*Constraints*: is_constructible_v<OuterAlloc, OuterA2> is true[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8865)
*Effects*: Initializes each allocator within the adaptor with the corresponding allocator rvalue
from other[.](#9.sentence-1)

View File

@@ -0,0 +1,146 @@
[allocator.adaptor.members]
# 20 Memory management library [[mem]](./#mem)
## 20.6 Class template scoped_allocator_adaptor [[allocator.adaptor]](allocator.adaptor#members)
### 20.6.4 Members [allocator.adaptor.members]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8873)
In the construct member functions,*OUTERMOST*(x) is*OUTERMOST*(x.outer_allocator()) if
the expression x.outer_allocator() is
valid ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")) andx otherwise;*OUTERMOST_ALLOC_TRAITS*(x) isallocator_traits<remove_reference_t<decltype(*OUTERMOST*(x))>>[.](#1.sentence-1)
[*Note [1](#note-1)*:
*OUTERMOST*(x) and*OUTERMOST_ALLOC_TRAITS*(x) are recursive operations[.](#1.sentence-2)
It
is incumbent upon the definition of outer_allocator() to ensure that the
recursion terminates[.](#1.sentence-3)
It will terminate for all instantiations ofscoped_allocator_adaptor[.](#1.sentence-4)
— *end note*]
[🔗](#lib:inner_allocator,scoped_allocator_adaptor)
`inner_allocator_type& inner_allocator() noexcept;
const inner_allocator_type& inner_allocator() const noexcept;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8897)
*Returns*: *this if sizeof...(InnerAllocs) is zero; otherwise,inner[.](#2.sentence-1)
[🔗](#lib:outer_allocator,scoped_allocator_adaptor)
`outer_allocator_type& outer_allocator() noexcept;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8909)
*Returns*: static_cast<OuterAlloc&>(*this)[.](#3.sentence-1)
[🔗](#lib:outer_allocator,scoped_allocator_adaptor_)
`const outer_allocator_type& outer_allocator() const noexcept;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8920)
*Returns*: static_cast<const OuterAlloc&>(*this)[.](#4.sentence-1)
[🔗](#lib:allocate,scoped_allocator_adaptor)
`pointer allocate(size_type n);
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8931)
*Returns*: allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)[.](#5.sentence-1)
[🔗](#lib:allocate,scoped_allocator_adaptor_)
`pointer allocate(size_type n, const_void_pointer hint);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8942)
*Returns*: allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)[.](#6.sentence-1)
[🔗](#lib:deallocate,scoped_allocator_adaptor)
`void deallocate(pointer p, size_type n) noexcept;
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8953)
*Effects*: As if by:allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n);
[🔗](#lib:max_size,scoped_allocator_adaptor)
`size_type max_size() const;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8965)
*Returns*: allocator_traits<OuterAlloc>::max_size(outer_allocator())[.](#8.sentence-1)
[🔗](#lib:construct,scoped_allocator_adaptor)
`template<class T, class... Args>
void construct(T* p, Args&&... args);
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8977)
*Effects*: Equivalent to:apply([p, this](auto&&... newargs) {*OUTERMOST_ALLOC_TRAITS*(*this)::construct(*OUTERMOST*(*this), p,
std::forward<decltype(newargs)>(newargs)...); },
uses_allocator_construction_args<T>(inner_allocator(),
std::forward<Args>(args)...));
[🔗](#lib:destroy,scoped_allocator_adaptor)
`template<class T>
void destroy(T* p);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8998)
*Effects*: Calls *OUTERMOST_ALLOC_TRAITS*(*this)::destroy(*OUTERMOST*(*this), p)[.](#10.sentence-1)
[🔗](#lib:select_on_container_copy_construction,scoped_allocator_adaptor)
`scoped_allocator_adaptor select_on_container_copy_construction() const;
`
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L9009)
*Returns*: A new scoped_allocator_adaptor object
where each allocator a1 within the adaptor
is initialized withallocator_traits<A1>::select_on_container_copy_construction(a2),
where A1 is the type of a1 anda2 is the corresponding allocator in *this[.](#11.sentence-1)

View File

@@ -0,0 +1,68 @@
[allocator.adaptor.syn]
# 20 Memory management library [[mem]](./#mem)
## 20.6 Class template scoped_allocator_adaptor [[allocator.adaptor]](allocator.adaptor#syn)
### 20.6.1 Header <scoped_allocator> synopsis [allocator.adaptor.syn]
[🔗](#header:%3cscoped_allocator%3e)
namespace std {// class template scoped_allocator_adaptortemplate<class OuterAlloc, class... InnerAlloc>class scoped_allocator_adaptor; // [[scoped.adaptor.operators]](scoped.adaptor.operators "20.6.5Operators"), scoped allocator operatorstemplate<class OuterA1, class OuterA2, class... InnerAllocs>bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;}
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8608)
The class template scoped_allocator_adaptor is an allocator template that
specifies an allocator resource (the outer allocator) to be used by a container (as any
other allocator does) and also specifies an inner allocator resource to be passed to the
constructor of every element within the container[.](#1.sentence-1)
This adaptor is instantiated with one
outer and zero or more inner allocator types[.](#1.sentence-2)
If instantiated with only one allocator
type, the inner allocator becomes the scoped_allocator_adaptor itself, thus
using the same allocator resource for the container and every element within the
container and, if the elements themselves are containers, each of their elements
recursively[.](#1.sentence-3)
If instantiated with more than one allocator, the first allocator is the
outer allocator for use by the container, the second allocator is passed to the
constructors of the container's elements, and, if the elements themselves are
containers, the third allocator is passed to the elements' elements, and so on[.](#1.sentence-4)
If
containers are nested to a depth greater than the number of allocators, the last
allocator is used repeatedly, as in the single-allocator case, for any remaining
recursions[.](#1.sentence-5)
[*Note [1](#note-1)*:
The scoped_allocator_adaptor is derived from the outer
allocator type so it can be substituted for the outer allocator type in most
expressions[.](#1.sentence-6)
— *end note*]
[🔗](#lib:scoped_allocator_adaptor)
namespace std {template<class OuterAlloc, class... InnerAllocs>class scoped_allocator_adaptor : public OuterAlloc {private:using OuterTraits = allocator_traits<OuterAlloc>; // *exposition only* scoped_allocator_adaptor<InnerAllocs...> inner; // *exposition only*public:using outer_allocator_type = OuterAlloc; using inner_allocator_type = *see below*; using value_type = typename OuterTraits::value_type; using size_type = typename OuterTraits::size_type; using difference_type = typename OuterTraits::difference_type; using pointer = typename OuterTraits::pointer; using const_pointer = typename OuterTraits::const_pointer; using void_pointer = typename OuterTraits::void_pointer; using const_void_pointer = typename OuterTraits::const_void_pointer; using propagate_on_container_copy_assignment = *see below*; using propagate_on_container_move_assignment = *see below*; using propagate_on_container_swap = *see below*; using is_always_equal = *see below*; template<class Tp> struct rebind {using other = scoped_allocator_adaptor< OuterTraits::template rebind_alloc<Tp>, InnerAllocs...>; };
scoped_allocator_adaptor(); template<class OuterA2> scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;
scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; template<class OuterA2> scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept; template<class OuterA2> scoped_allocator_adaptor( scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; ~scoped_allocator_adaptor();
inner_allocator_type& inner_allocator() noexcept; const inner_allocator_type& inner_allocator() const noexcept;
outer_allocator_type& outer_allocator() noexcept; const outer_allocator_type& outer_allocator() const noexcept;
pointer allocate(size_type n);
pointer allocate(size_type n, const_void_pointer hint); void deallocate(pointer p, size_type n);
size_type max_size() const; template<class T, class... Args>void construct(T* p, Args&&... args); template<class T>void destroy(T* p);
scoped_allocator_adaptor select_on_container_copy_construction() const; }; template<class OuterAlloc, class... InnerAllocs> scoped_allocator_adaptor(OuterAlloc, InnerAllocs...)-> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;}

View File

@@ -0,0 +1,65 @@
[allocator.adaptor.types]
# 20 Memory management library [[mem]](./#mem)
## 20.6 Class template scoped_allocator_adaptor [[allocator.adaptor]](allocator.adaptor#types)
### 20.6.2 Member types [allocator.adaptor.types]
[🔗](#lib:inner_allocator_type,scoped_allocator_adaptor)
`using inner_allocator_type = see below;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8722)
*Type*: scoped_allocator_adaptor<OuterAlloc> if sizeof...(InnerAllocs) is
zero; otherwise,
scoped_allocator_adaptor<InnerAllocs...>[.](#1.sentence-2)
[🔗](#lib:propagate_on_container_copy_assignment,scoped_allocator_adaptor)
`using propagate_on_container_copy_assignment = see below;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8733)
*Type*: true_type ifallocator_traits<A>::propagate_on_container_copy_assignment::value istrue for any A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#2.sentence-1)
[🔗](#lib:propagate_on_container_move_assignment,scoped_allocator_adaptor)
`using propagate_on_container_move_assignment = see below;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8746)
*Type*: true_type ifallocator_traits<A>::propagate_on_container_move_assignment::value istrue for any A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#3.sentence-1)
[🔗](#lib:propagate_on_container_swap,scoped_allocator_adaptor)
`using propagate_on_container_swap = see below;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8759)
*Type*: true_type ifallocator_traits<A>::propagate_on_container_swap::value istrue for any A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#4.sentence-1)
[🔗](#lib:is_always_equal,scoped_allocator_adaptor)
`using is_always_equal = see below;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8772)
*Type*: true_type ifallocator_traits<A>::is_always_equal::value istrue for every A in the set of OuterAlloc andInnerAllocs...; otherwise, false_type[.](#5.sentence-1)

View File

@@ -0,0 +1,21 @@
[allocator.globals]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.globals)
### 20.2.10 The default allocator [[default.allocator]](default.allocator#allocator.globals)
#### 20.2.10.3 Operators [allocator.globals]
[🔗](#lib:operator==,allocator)
`template<class T, class U>
constexpr bool operator==(const allocator<T>&, const allocator<U>&) noexcept;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2104)
*Returns*: true[.](#1.sentence-1)

View File

@@ -0,0 +1,129 @@
[allocator.members]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.members)
### 20.2.10 The default allocator [[default.allocator]](default.allocator#allocator.members)
#### 20.2.10.2 Members [allocator.members]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1994)
Except for the destructor, member functions of the default allocator shall not introduce
data races ([[intro.multithread]](intro.multithread "6.10.2Multi-threaded executions and data races")) as a result of concurrent calls to those member
functions from different threads[.](#1.sentence-1)
Calls to these functions that allocate or deallocate a
particular unit of storage shall occur in a single total order, and each such
deallocation call shall happen before the next allocation (if any) in this order[.](#1.sentence-2)
[🔗](#lib:allocate,allocator)
`constexpr T* allocate(size_t n);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2007)
*Mandates*: T is not an incomplete type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2011)
*Returns*: A pointer to the initial element of an array of n T[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2015)
*Throws*: bad_array_new_length ifnumeric_limits<size_t>::max() / sizeof(T) < n, orbad_alloc if the storage cannot be obtained[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2021)
*Remarks*: The storage for the array
is obtained by calling ::operator new ([[new.delete]](new.delete "17.6.3Storage allocation and deallocation")),
but it is unspecified when or how often this
function is called[.](#5.sentence-1)
This function starts the lifetime of the array object,
but not that of any of the array elements[.](#5.sentence-2)
[🔗](#lib:allocate_at_least,allocator)
`constexpr allocation_result<T*> allocate_at_least(size_t n);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2037)
*Mandates*: T is not an incomplete type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General"))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2041)
*Returns*: allocation_result<T*>{ptr, count},
where ptr is a pointer to
the initial element of an array of count T andcount ≥ n[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2048)
*Throws*: bad_array_new_length if numeric_limits<size_t>::max() / sizeof(T) < n,
or bad_alloc if the storage cannot be obtained[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2054)
*Remarks*: The storage for the array is obtained by calling ::operator new,
but it is unspecified when or how often this function is called[.](#9.sentence-1)
This function starts the lifetime of the array object,
but not that of any of the array elements[.](#9.sentence-2)
[🔗](#lib:deallocate,allocator)
`constexpr void deallocate(T* p, size_t n);
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2068)
*Preconditions*:
- [(10.1)](#10.1)
If p is memory that was obtained by a call to allocate_at_least,
let ret be the value returned andreq be the value passed as the first argument to that call[.](#10.1.sentence-1)
p is equal to ret.ptr andn is a value such that req ≤ n ≤ ret.count[.](#10.1.sentence-2)
- [(10.2)](#10.2)
Otherwise, p is a pointer value obtained from allocate[.](#10.2.sentence-1)
n equals the value passed as the first argument
to the invocation of allocate which returned p[.](#10.2.sentence-2)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2083)
*Effects*: Deallocates the storage referenced by p[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L2087)
*Remarks*: Uses::operator delete ([[new.delete]](new.delete "17.6.3Storage allocation and deallocation")),
but it is unspecified
when this function is called[.](#12.sentence-1)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
[allocator.requirements.completeness]
# 16 Library introduction [[library]](./#library)
## 16.4 Library-wide requirements [[requirements]](requirements#allocator.requirements.completeness)
### 16.4.4 Requirements on types and expressions [[utility.requirements]](utility.requirements#allocator.requirements.completeness)
#### 16.4.4.6 *Cpp17Allocator* requirements [[allocator.requirements]](allocator.requirements#completeness)
#### 16.4.4.6.2 Allocator completeness requirements [allocator.requirements.completeness]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2964)
If X is an allocator class for type T,X additionally meets the allocator completeness requirements if,
whether or not T is a complete type:
- [(1.1)](#1.1)
X is a complete type, and
- [(1.2)](#1.2)
all the member types of [allocator_traits<X>](allocator.traits "20.2.9Allocator traits[allocator.traits]") other than value_type are complete types[.](#1.sentence-1)

File diff suppressed because it is too large Load Diff

25
cppdraft/allocator/tag.md Normal file
View File

@@ -0,0 +1,25 @@
[allocator.tag]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.tag)
### 20.2.7 Allocator argument tag [allocator.tag]
[🔗](#lib:allocator_arg_t)
`namespace std {
struct allocator_arg_t { explicit allocator_arg_t() = default; };
inline constexpr allocator_arg_t allocator_arg{};
}
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1271)
The allocator_arg_t struct is an empty class type used as a unique type to
disambiguate constructor and function overloading[.](#1.sentence-1)
Specifically, several types (seetuple [[tuple]](tuple "22.4Tuples")) have constructors with allocator_arg_t as the first
argument, immediately followed by an argument of a type that meets the[*Cpp17Allocator*](allocator.requirements.general#:Cpp17Allocator "16.4.4.6.1General[allocator.requirements.general]") requirements ([[allocator.requirements.general]](allocator.requirements.general "16.4.4.6.1General"))[.](#1.sentence-2)

View File

@@ -0,0 +1,292 @@
[allocator.traits]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.traits)
### 20.2.9 Allocator traits [allocator.traits]
#### [20.2.9.1](#general) General [[allocator.traits.general]](allocator.traits.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1640)
The class template allocator_traits supplies a uniform interface to all
allocator types[.](#general-1.sentence-1)
An allocator cannot be a non-class type, however, even if allocator_traits supplies the entire required interface[.](#general-1.sentence-2)
[*Note [1](#general-note-1)*:
Thus, it is always possible to create
a derived class from an allocator[.](#general-1.sentence-3)
— *end note*]
If a program declares
an explicit or partial specialization of allocator_traits,
the program is ill-formed, no diagnostic required[.](#general-1.sentence-4)
[🔗](#lib:allocator_traits)
namespace std {template<class Alloc> struct allocator_traits {using allocator_type = Alloc; using value_type = typename Alloc::value_type; using pointer = *see below*; using const_pointer = *see below*; using void_pointer = *see below*; using const_void_pointer = *see below*; using difference_type = *see below*; using size_type = *see below*; using propagate_on_container_copy_assignment = *see below*; using propagate_on_container_move_assignment = *see below*; using propagate_on_container_swap = *see below*; using is_always_equal = *see below*; template<class T> using rebind_alloc = *see below*; template<class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; static constexpr pointer allocate(Alloc& a, size_type n); static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n); static constexpr void deallocate(Alloc& a, pointer p, size_type n); template<class T, class... Args>static constexpr void construct(Alloc& a, T* p, Args&&... args); template<class T>static constexpr void destroy(Alloc& a, T* p); static constexpr size_type max_size(const Alloc& a) noexcept; static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); };}
#### [20.2.9.2](#types) Member types [[allocator.traits.types]](allocator.traits.types)
[🔗](#lib:pointer,allocator_traits)
`using pointer = see below;
`
[1](#types-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1705)
*Type*: Alloc::pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise, value_type*[.](#types-1.sentence-1)
[🔗](#lib:const_pointer,allocator_traits)
`using const_pointer = see below;
`
[2](#types-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1717)
*Type*: Alloc::const_pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::const_pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::rebind<const value_type>[.](#types-2.sentence-1)
[🔗](#lib:void_pointer,allocator_traits)
`using void_pointer = see below;
`
[3](#types-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1730)
*Type*: Alloc::void_pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::void_pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::rebind<void>[.](#types-3.sentence-1)
[🔗](#lib:const_void_pointer,allocator_traits)
`using const_void_pointer = see below;
`
[4](#types-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1743)
*Type*: Alloc::const_void_pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::const_void_pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::rebind<const void>[.](#types-4.sentence-1)
[🔗](#lib:difference_type,allocator_traits)
`using difference_type = see below;
`
[5](#types-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1756)
*Type*: Alloc::difference_type if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::difference_type is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::difference_type[.](#types-5.sentence-1)
[🔗](#lib:size_type,allocator_traits)
`using size_type = see below;
`
[6](#types-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1769)
*Type*: Alloc::size_type if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::size_type is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,make_unsigned_t<difference_type>[.](#types-6.sentence-1)
[🔗](#lib:propagate_on_container_copy_assignment,allocator_traits)
`using propagate_on_container_copy_assignment = see below;
`
[7](#types-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1782)
*Type*: Alloc::propagate_on_container_copy_assignment if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::propagate_on_container_copy_assignment is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwisefalse_type[.](#types-7.sentence-1)
[🔗](#lib:propagate_on_container_move_assignment,allocator_traits)
`using propagate_on_container_move_assignment = see below;
`
[8](#types-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1795)
*Type*: Alloc::propagate_on_container_move_assignment if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::propagate_on_container_move_assignment is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwisefalse_type[.](#types-8.sentence-1)
[🔗](#lib:propagate_on_container_swap,allocator_traits)
`using propagate_on_container_swap = see below;
`
[9](#types-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1808)
*Type*: Alloc::propagate_on_container_swap if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::propagate_on_container_swap is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwisefalse_type[.](#types-9.sentence-1)
[🔗](#lib:is_always_equal,allocator_traits)
`using is_always_equal = see below;
`
[10](#types-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1821)
*Type*: Alloc::is_always_equal if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::is_always_equal is valid and denotes a type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"));
otherwise is_empty<Alloc>::type[.](#types-10.sentence-1)
[🔗](#lib:rebind_alloc,allocator_traits)
`template<class T> using rebind_alloc = see below;
`
[11](#types-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1834)
*Alias template*: Alloc::rebind<T>::other if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::rebind<T>::other is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,Alloc<T, Args> if Alloc is a class template instantiation
of the form Alloc<U, Args>, where Args is zero or more type arguments;
otherwise, the instantiation of rebind_alloc is ill-formed[.](#types-11.sentence-1)
#### [20.2.9.3](#members) Static member functions [[allocator.traits.members]](allocator.traits.members)
[🔗](#lib:allocate,allocator_traits)
`static constexpr pointer allocate(Alloc& a, size_type n);
`
[1](#members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1851)
*Returns*: a.allocate(n)[.](#members-1.sentence-1)
[🔗](#lib:allocate,allocator_traits_)
`static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
`
[2](#members-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1862)
*Returns*: a.allocate(n, hint) if that expression is well-formed; otherwise, a.allocate(n)[.](#members-2.sentence-1)
[🔗](#lib:allocate_at_least,allocator_traits)
`static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n);
`
[3](#members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1873)
*Returns*: a.allocate_at_least(n) if that expression is well-formed;
otherwise, {a.allocate(n), n}[.](#members-3.sentence-1)
[🔗](#lib:deallocate,allocator_traits)
`static constexpr void deallocate(Alloc& a, pointer p, size_type n);
`
[4](#members-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1885)
*Effects*: Calls a.deallocate(p, n)[.](#members-4.sentence-1)
[5](#members-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1889)
*Throws*: Nothing[.](#members-5.sentence-1)
[🔗](#lib:construct,allocator_traits)
`template<class T, class... Args>
static constexpr void construct(Alloc& a, T* p, Args&&... args);
`
[6](#members-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1901)
*Effects*: Calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed;
otherwise, invokes construct_at(p, std::forward<Args>(args)...)[.](#members-6.sentence-1)
[🔗](#lib:destroy,allocator_traits)
`template<class T>
static constexpr void destroy(Alloc& a, T* p);
`
[7](#members-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1915)
*Effects*: Calls a.destroy(p) if that call is well-formed; otherwise, invokesdestroy_at(p)[.](#members-7.sentence-1)
[🔗](#lib:max_size,allocator_traits)
`static constexpr size_type max_size(const Alloc& a) noexcept;
`
[8](#members-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1927)
*Returns*: a.max_size() if that expression is well-formed; otherwise,numeric_limits<size_type>::max() / sizeof(value_type)[.](#members-8.sentence-1)
[🔗](#lib:select_on_container_copy_construction,allocator_traits)
`static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs);
`
[9](#members-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1939)
*Returns*: rhs.select_on_container_copy_construction() if that expression is
well-formed; otherwise, rhs[.](#members-9.sentence-1)
#### [20.2.9.4](#other) Other [[allocator.traits.other]](allocator.traits.other)
[1](#other-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1947)
The class template allocation_result has
the template parameters, data members, and special members specified above[.](#other-1.sentence-1)
It has no base classes or members other than those specified[.](#other-1.sentence-2)

View File

@@ -0,0 +1,33 @@
[allocator.traits.general]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.traits.general)
### 20.2.9 Allocator traits [[allocator.traits]](allocator.traits#general)
#### 20.2.9.1 General [allocator.traits.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1640)
The class template allocator_traits supplies a uniform interface to all
allocator types[.](#1.sentence-1)
An allocator cannot be a non-class type, however, even if allocator_traits supplies the entire required interface[.](#1.sentence-2)
[*Note [1](#note-1)*:
Thus, it is always possible to create
a derived class from an allocator[.](#1.sentence-3)
— *end note*]
If a program declares
an explicit or partial specialization of allocator_traits,
the program is ill-formed, no diagnostic required[.](#1.sentence-4)
[🔗](#lib:allocator_traits)
namespace std {template<class Alloc> struct allocator_traits {using allocator_type = Alloc; using value_type = typename Alloc::value_type; using pointer = *see below*; using const_pointer = *see below*; using void_pointer = *see below*; using const_void_pointer = *see below*; using difference_type = *see below*; using size_type = *see below*; using propagate_on_container_copy_assignment = *see below*; using propagate_on_container_move_assignment = *see below*; using propagate_on_container_swap = *see below*; using is_always_equal = *see below*; template<class T> using rebind_alloc = *see below*; template<class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; static constexpr pointer allocate(Alloc& a, size_type n); static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint); static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n); static constexpr void deallocate(Alloc& a, pointer p, size_type n); template<class T, class... Args>static constexpr void construct(Alloc& a, T* p, Args&&... args); template<class T>static constexpr void destroy(Alloc& a, T* p); static constexpr size_type max_size(const Alloc& a) noexcept; static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs); };}

View File

@@ -0,0 +1,108 @@
[allocator.traits.members]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.traits.members)
### 20.2.9 Allocator traits [[allocator.traits]](allocator.traits#members)
#### 20.2.9.3 Static member functions [allocator.traits.members]
[🔗](#lib:allocate,allocator_traits)
`static constexpr pointer allocate(Alloc& a, size_type n);
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1851)
*Returns*: a.allocate(n)[.](#1.sentence-1)
[🔗](#lib:allocate,allocator_traits_)
`static constexpr pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1862)
*Returns*: a.allocate(n, hint) if that expression is well-formed; otherwise, a.allocate(n)[.](#2.sentence-1)
[🔗](#lib:allocate_at_least,allocator_traits)
`static constexpr allocation_result<pointer, size_type> allocate_at_least(Alloc& a, size_type n);
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1873)
*Returns*: a.allocate_at_least(n) if that expression is well-formed;
otherwise, {a.allocate(n), n}[.](#3.sentence-1)
[🔗](#lib:deallocate,allocator_traits)
`static constexpr void deallocate(Alloc& a, pointer p, size_type n);
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1885)
*Effects*: Calls a.deallocate(p, n)[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1889)
*Throws*: Nothing[.](#5.sentence-1)
[🔗](#lib:construct,allocator_traits)
`template<class T, class... Args>
static constexpr void construct(Alloc& a, T* p, Args&&... args);
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1901)
*Effects*: Calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed;
otherwise, invokes construct_at(p, std::forward<Args>(args)...)[.](#6.sentence-1)
[🔗](#lib:destroy,allocator_traits)
`template<class T>
static constexpr void destroy(Alloc& a, T* p);
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1915)
*Effects*: Calls a.destroy(p) if that call is well-formed; otherwise, invokesdestroy_at(p)[.](#7.sentence-1)
[🔗](#lib:max_size,allocator_traits)
`static constexpr size_type max_size(const Alloc& a) noexcept;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1927)
*Returns*: a.max_size() if that expression is well-formed; otherwise,numeric_limits<size_type>::max() / sizeof(value_type)[.](#8.sentence-1)
[🔗](#lib:select_on_container_copy_construction,allocator_traits)
`static constexpr Alloc select_on_container_copy_construction(const Alloc& rhs);
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1939)
*Returns*: rhs.select_on_container_copy_construction() if that expression is
well-formed; otherwise, rhs[.](#9.sentence-1)

View File

@@ -0,0 +1,18 @@
[allocator.traits.other]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.traits.other)
### 20.2.9 Allocator traits [[allocator.traits]](allocator.traits#other)
#### 20.2.9.4 Other [allocator.traits.other]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1947)
The class template allocation_result has
the template parameters, data members, and special members specified above[.](#1.sentence-1)
It has no base classes or members other than those specified[.](#1.sentence-2)

View File

@@ -0,0 +1,154 @@
[allocator.traits.types]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.traits.types)
### 20.2.9 Allocator traits [[allocator.traits]](allocator.traits#types)
#### 20.2.9.2 Member types [allocator.traits.types]
[🔗](#lib:pointer,allocator_traits)
`using pointer = see below;
`
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1705)
*Type*: Alloc::pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise, value_type*[.](#1.sentence-1)
[🔗](#lib:const_pointer,allocator_traits)
`using const_pointer = see below;
`
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1717)
*Type*: Alloc::const_pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::const_pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::rebind<const value_type>[.](#2.sentence-1)
[🔗](#lib:void_pointer,allocator_traits)
`using void_pointer = see below;
`
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1730)
*Type*: Alloc::void_pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::void_pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::rebind<void>[.](#3.sentence-1)
[🔗](#lib:const_void_pointer,allocator_traits)
`using const_void_pointer = see below;
`
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1743)
*Type*: Alloc::const_void_pointer if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::const_void_pointer is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::rebind<const void>[.](#4.sentence-1)
[🔗](#lib:difference_type,allocator_traits)
`using difference_type = see below;
`
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1756)
*Type*: Alloc::difference_type if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::difference_type is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,pointer_traits<pointer>::difference_type[.](#5.sentence-1)
[🔗](#lib:size_type,allocator_traits)
`using size_type = see below;
`
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1769)
*Type*: Alloc::size_type if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::size_type is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,make_unsigned_t<difference_type>[.](#6.sentence-1)
[🔗](#lib:propagate_on_container_copy_assignment,allocator_traits)
`using propagate_on_container_copy_assignment = see below;
`
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1782)
*Type*: Alloc::propagate_on_container_copy_assignment if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::propagate_on_container_copy_assignment is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwisefalse_type[.](#7.sentence-1)
[🔗](#lib:propagate_on_container_move_assignment,allocator_traits)
`using propagate_on_container_move_assignment = see below;
`
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1795)
*Type*: Alloc::propagate_on_container_move_assignment if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::propagate_on_container_move_assignment is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwisefalse_type[.](#8.sentence-1)
[🔗](#lib:propagate_on_container_swap,allocator_traits)
`using propagate_on_container_swap = see below;
`
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1808)
*Type*: Alloc::propagate_on_container_swap if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::propagate_on_container_swap is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwisefalse_type[.](#9.sentence-1)
[🔗](#lib:is_always_equal,allocator_traits)
`using is_always_equal = see below;
`
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1821)
*Type*: Alloc::is_always_equal if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::is_always_equal is valid and denotes a type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"));
otherwise is_empty<Alloc>::type[.](#10.sentence-1)
[🔗](#lib:rebind_alloc,allocator_traits)
`template<class T> using rebind_alloc = see below;
`
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1834)
*Alias template*: Alloc::rebind<T>::other if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Alloc::rebind<T>::other is valid and denotes a
type ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")); otherwise,Alloc<T, Args> if Alloc is a class template instantiation
of the form Alloc<U, Args>, where Args is zero or more type arguments;
otherwise, the instantiation of rebind_alloc is ill-formed[.](#11.sentence-1)

343
cppdraft/allocator/uses.md Normal file
View File

@@ -0,0 +1,343 @@
[allocator.uses]
# 20 Memory management library [[mem]](./#mem)
## 20.2 Memory [[memory]](memory#allocator.uses)
### 20.2.8 uses_allocator [allocator.uses]
#### [20.2.8.1](#trait) uses_allocator trait [[allocator.uses.trait]](allocator.uses.trait)
[🔗](#lib:uses_allocator)
`template<class T, class Alloc> struct uses_allocator;
`
[1](#trait-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[.](#trait-1.sentence-1)
Meets the [*Cpp17BinaryTypeTrait*](meta.rqmts#:Cpp17BinaryTypeTrait "21.3.2Requirements[meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2Requirements"))[.](#trait-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[.](#trait-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)](#trait-1.1)
the first argument of a constructor has type allocator_arg_t and the
second argument has type Alloc or
- [(1.2)](#trait-1.2)
the last argument of a constructor has type Alloc[.](#trait-1.sentence-4)
#### [20.2.8.2](#construction) Uses-allocator construction [[allocator.uses.construction]](allocator.uses.construction)
[1](#construction-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[.](#construction-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[.](#construction-1.sentence-2)
[2](#construction-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)](#construction-2.1)
If T does not use an allocator compatible with alloc,
then alloc is ignored[.](#construction-2.1.sentence-1)
- [(2.2)](#construction-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[.](#construction-2.2.sentence-1)
- [(2.3)](#construction-2.3)
Otherwise, if T has a constructor invocable as T(args..., alloc) (trailing-allocator convention),
then uses-allocator construction chooses this constructor form[.](#construction-2.3.sentence-1)
[3](#construction-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[.](#construction-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[.](#construction-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[.](#construction-3.sentence-3)
[*Note [1](#construction-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[.](#construction-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](#construction-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1364)
*Constraints*: remove_cv_t<T> is not a specialization of pair[.](#construction-4.sentence-1)
[5](#construction-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1368)
*Returns*: A tuple value determined as follows:
- [(5.1)](#construction-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)...)[.](#construction-5.1.sentence-1)
- [(5.2)](#construction-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)](#construction-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)[.](#construction-5.3.sentence-1)
- [(5.4)](#construction-5.4)
Otherwise, the program is ill-formed[.](#construction-5.4.sentence-1)
[*Note [2](#construction-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[.](#construction-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](#construction-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1407)
Let T1 be T::first_type[.](#construction-6.sentence-1)
Let T2 be T::second_type[.](#construction-6.sentence-2)
[7](#construction-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1411)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#construction-7.sentence-1)
[8](#construction-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](#construction-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1439)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#construction-9.sentence-1)
[10](#construction-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](#construction-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1460)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#construction-11.sentence-1)
[12](#construction-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](#construction-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1485)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#construction-13.sentence-1)
[14](#construction-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](#construction-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L1510)
*Constraints*: remove_cv_t<T> is a specialization of pair[.](#construction-15.sentence-1)
[16](#construction-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](#construction-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[.](#construction-17.sentence-1)
[18](#construction-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](#construction-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](#construction-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)](#construction-20.1)
remove_cvref_t<U> is a specialization of ranges::subrange, or
- [(20.2)](#construction-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[.](#construction-20.sentence-1)
[21](#construction-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](#construction-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[.](#construction-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](#construction-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](#construction-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,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)