[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.2 Requirements [meta.rqmts]") requirements ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements"))[.](#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.3 Qualified names [expr.prim.id.qual]") T​::​allocator_type is valid and denotes a type ([[temp.deduct]](temp.deduct "13.10.3 Template 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.2 Uses-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.2 Header <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.2 Header <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)...));
