[utility.requirements]

# 16 Library introduction [[library]](./#library)

## 16.4 Library-wide requirements [[requirements]](requirements#utility.requirements)

### 16.4.4 Requirements on types and expressions [utility.requirements]

#### [16.4.4.1](#general) General [[utility.requirements.general]](utility.requirements.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1766)

[[utility.arg.requirements]](#utility.arg.requirements "16.4.4.2 Template argument requirements") describes requirements on types and expressions used to instantiate templates
defined in the C++ standard library[.](#general-1.sentence-1)

[[swappable.requirements]](#swappable.requirements "16.4.4.3 Swappable requirements") describes the requirements on swappable types and
swappable expressions[.](#general-1.sentence-2)

[[nullablepointer.requirements]](#nullablepointer.requirements "16.4.4.4 Cpp17NullablePointer requirements") describes the requirements on pointer-like
types that support null values[.](#general-1.sentence-3)

[[hash.requirements]](#hash.requirements "16.4.4.5 Cpp17Hash requirements") describes the requirements on hash function objects[.](#general-1.sentence-4)

[[allocator.requirements]](#allocator.requirements "16.4.4.6 Cpp17Allocator requirements") describes the requirements on storage
allocators[.](#general-1.sentence-5)

#### [16.4.4.2](#utility.arg.requirements) Template argument requirements [[utility.arg.requirements]](utility.arg.requirements)

[1](#utility.arg.requirements-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1780)

The template definitions in the C++ standard library
refer to various named requirements whose details are set out in
Tables [28](#tab:cpp17.equalitycomparable "Table 28: Cpp17EqualityComparable requirements")â[35](#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements")[.](#utility.arg.requirements-1.sentence-1)

In these tables,

- [(1.1)](#utility.arg.requirements-1.1)

T denotes an object or reference type to be
supplied by a C++ program instantiating a template,

- [(1.2)](#utility.arg.requirements-1.2)

a,b, andc denote values of type (possibly const) T,

- [(1.3)](#utility.arg.requirements-1.3)

s and t denote modifiable lvalues of type T,

- [(1.4)](#utility.arg.requirements-1.4)

u denotes an identifier,

- [(1.5)](#utility.arg.requirements-1.5)

rv denotes an rvalue of type T, and

- [(1.6)](#utility.arg.requirements-1.6)

v denotes an lvalue of type (possibly const) T or an
rvalue of type const T[.](#utility.arg.requirements-1.sentence-2)

[2](#utility.arg.requirements-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1804)

In general, a default constructor is not required[.](#utility.arg.requirements-2.sentence-1)

Certain container class
member function signatures specify T() as a default argument[.](#utility.arg.requirements-2.sentence-2)

T() shall be a well-defined expression ([[dcl.init]](dcl.init "9.5 Initializers")) if one of those
signatures is called using the [default argument](dcl.fct.default "9.3.4.7 Default arguments [dcl.fct.default]")[.](#utility.arg.requirements-2.sentence-3)

Table [28](#tab:cpp17.equalitycomparable) — *Cpp17EqualityComparable* requirements [[tab:cpp17.equalitycomparable]](./tab:cpp17.equalitycomparable)  

| [ð](#tab:cpp17.equalitycomparable-row-1)<br>**Expression** | **Return type** | **Requirement** |
| --- | --- | --- |
| [ð](#tab:cpp17.equalitycomparable-row-2)<br>a == b | decltype(a == b) models *boolean-testable* | == is an equivalence relation, that is, it has the following properties: <br> <br>For all a, a == a[.](#tab:cpp17.equalitycomparable-row-2-column-3-sentence-1)<br>   If a == b, then b == a[.](#tab:cpp17.equalitycomparable-row-2-column-3-sentence-1)<br>   If a == b and b == c, then a == c[.](#tab:cpp17.equalitycomparable-row-2-column-3-sentence-1) |

Table [29](#tab:cpp17.lessthancomparable) — *Cpp17LessThanComparable* requirements [[tab:cpp17.lessthancomparable]](./tab:cpp17.lessthancomparable)  

| [ð](#tab:cpp17.lessthancomparable-row-1)<br>**Expression** | **Return type** | **Requirement** |
| --- | --- | --- |
| [ð](#tab:cpp17.lessthancomparable-row-2)<br>a < b | decltype(a < b) models *boolean-testable* | < is a strict weak ordering relation ([[alg.sorting]](alg.sorting "26.8 Sorting and related operations")) |

Table [30](#tab:cpp17.defaultconstructible) — *Cpp17DefaultConstructible* requirements [[tab:cpp17.defaultconstructible]](./tab:cpp17.defaultconstructible)  

| [ð](#tab:cpp17.defaultconstructible-row-1)<br>**Expression** | **Post-condition** |
| --- | --- |
| [ð](#tab:cpp17.defaultconstructible-row-2)<br>T t; | object t is default-initialized |
| [ð](#tab:cpp17.defaultconstructible-row-3)<br>T u{}; | object u is value-initialized or aggregate-initialized |
| [ð](#tab:cpp17.defaultconstructible-row-4)<br>T()   T{} | an object of type T is value-initialized  or aggregate-initialized |

Table [31](#tab:cpp17.moveconstructible) — *Cpp17MoveConstructible* requirements [[tab:cpp17.moveconstructible]](./tab:cpp17.moveconstructible)  

| [ð](#tab:cpp17.moveconstructible-row-1)<br>**Expression** | **Post-condition** |
| --- | --- |
| [ð](#tab:cpp17.moveconstructible-row-2)<br>T u = rv; | u is equivalent to the value of rv before the construction |
| [ð](#tab:cpp17.moveconstructible-row-3)<br>T(rv) | T(rv) is equivalent to the value of rv before the construction |
| [ð](#tab:cpp17.moveconstructible-row-4)<br>rv's state is unspecified <br>[*Note [1](#tab:cpp17.moveconstructible-row-4-column-1-note-1)*:<br>rv must still meet the requirements of the library  component that is using it[.](#tab:cpp17.moveconstructible-row-4-column-1-sentence-1)<br>The operations listed in those requirements must  work as specified whether rv has been moved from or not[.](#tab:cpp17.moveconstructible-row-4-column-1-sentence-2) â *end note*] | |

Table [32](#tab:cpp17.copyconstructible) — *Cpp17CopyConstructible* requirements (in addition to [*Cpp17MoveConstructible*](#:Cpp17MoveConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]")) [[tab:cpp17.copyconstructible]](./tab:cpp17.copyconstructible)  

| [ð](#tab:cpp17.copyconstructible-row-1)<br>**Expression** | **Post-condition** |
| --- | --- |
| [ð](#tab:cpp17.copyconstructible-row-2)<br>T u = v; | the value of v is unchanged and is equivalent to  u |
| [ð](#tab:cpp17.copyconstructible-row-3)<br>T(v) | the value of v is unchanged and is equivalent to T(v) |

Table [33](#tab:cpp17.moveassignable) — *Cpp17MoveAssignable* requirements [[tab:cpp17.moveassignable]](./tab:cpp17.moveassignable)  

| [ð](#tab:cpp17.moveassignable-row-1)<br>**Expression** | **Return type** | **Return value** | **Post-condition** |
| --- | --- | --- | --- |
| [ð](#tab:cpp17.moveassignable-row-2)<br>t = rv | T& | t | If t and rv do not refer to the same object,  t is equivalent to the value of rv before the assignment |
| [ð](#tab:cpp17.moveassignable-row-3)<br>rv's state is unspecified[.](#tab:cpp17.moveassignable-row-3-column-1-sentence-1)<br>[*Note [2](#tab:cpp17.moveassignable-row-3-column-1-note-2)*:<br>rv must still meet the requirements of the library  component that is using it, whether or not t and rv refer to the same object[.](#tab:cpp17.moveassignable-row-3-column-1-sentence-2)<br>The operations listed in those requirements must  work as specified whether rv has been moved from or not[.](#tab:cpp17.moveassignable-row-3-column-1-sentence-3) â *end note*] | | | |

Table [34](#tab:cpp17.copyassignable) — *Cpp17CopyAssignable* requirements (in addition to [*Cpp17MoveAssignable*](#:Cpp17MoveAssignable "16.4.4.2 Template argument requirements [utility.arg.requirements]")) [[tab:cpp17.copyassignable]](./tab:cpp17.copyassignable)  

| [ð](#tab:cpp17.copyassignable-row-1)<br>**Expression** | **Return type** | **Return value** | **Post-condition** |
| --- | --- | --- | --- |
| [ð](#tab:cpp17.copyassignable-row-2)<br>t = v | T& | t | t is equivalent to v, the value of v is unchanged |

Table [35](#tab:cpp17.destructible) — *Cpp17Destructible* requirements [[tab:cpp17.destructible]](./tab:cpp17.destructible)  

| [ð](#tab:cpp17.destructible-row-1)<br>**Expression** | **Post-condition** |
| --- | --- |
| [ð](#tab:cpp17.destructible-row-2)<br>u.~T() | All resources owned by u are reclaimed, no exception is propagated[.](#tab:cpp17.destructible-row-2-column-2-sentence-1) |
| [ð](#tab:cpp17.destructible-row-3)<br>[*Note [3](#tab:cpp17.destructible-row-3-column-1-note-3)*:<br>Array types and non-object types are not [*Cpp17Destructible*](#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]")[.](#tab:cpp17.destructible-row-3-column-1-sentence-1) â *end note*] | |

#### [16.4.4.3](#swappable.requirements) Swappable requirements [[swappable.requirements]](swappable.requirements)

[1](#swappable.requirements-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1913)

This subclause provides definitions for swappable types and expressions[.](#swappable.requirements-1.sentence-1)

In these
definitions, let t denote an expression of type T, and let u denote an expression of type U[.](#swappable.requirements-1.sentence-2)

[2](#swappable.requirements-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1918)

An object t is [*swappable with*](#def:swappable_with "16.4.4.3 Swappable requirements [swappable.requirements]") an object u if and only if

- [(2.1)](#swappable.requirements-2.1)

the expressions swap(t, u) and swap(u, t) are valid when
evaluated in the context described below, and

- [(2.2)](#swappable.requirements-2.2)

these expressions have the following effects:
  * [(2.2.1)](#swappable.requirements-2.2.1)

the object referred to by t has the value originally held by u and

  * [(2.2.2)](#swappable.requirements-2.2.2)

the object referred to by u has the value originally held by t[.](#swappable.requirements-2.sentence-1)

[3](#swappable.requirements-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1931)

The context in which swap(t, u) and swap(u, t) are evaluated shall
ensure that a binary non-member function named âswapâ is selected via [overload
resolution](over.match "12.2 Overload resolution [over.match]") on a candidate set that includes:

- [(3.1)](#swappable.requirements-3.1)

the two swap function templates defined in[<utility>](utility.syn#header:%3cutility%3e "22.2.1 Header <utility> synopsis [utility.syn]") and

- [(3.2)](#swappable.requirements-3.2)

the lookup set produced by [argument-dependent lookup](basic.lookup.argdep "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]")[.](#swappable.requirements-3.sentence-1)

[*Note [1](#swappable.requirements-note-1)*:

If T and U are both fundamental types or arrays of
fundamental types and the declarations from the header [<utility>](utility.syn#header:%3cutility%3e "22.2.1 Header <utility> synopsis [utility.syn]") are in
scope, the overall lookup set described above is equivalent to that of the
qualified name lookup applied to the expression std​::​swap(t, u) orstd​::​swap(u, t) as appropriate[.](#swappable.requirements-3.sentence-2)

â *end note*]

[*Note [2](#swappable.requirements-note-2)*:

It is unspecified whether a library component that has a swappable
requirement includes the header [<utility>](utility.syn#header:%3cutility%3e "22.2.1 Header <utility> synopsis [utility.syn]") to ensure an appropriate
evaluation context[.](#swappable.requirements-3.sentence-3)

â *end note*]

[4](#swappable.requirements-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1954)

An rvalue or lvalue t is [*swappable*](#def:swappable "16.4.4.3 Swappable requirements [swappable.requirements]") if and only if t is
swappable with any rvalue or lvalue, respectively, of type T[.](#swappable.requirements-4.sentence-1)

[5](#swappable.requirements-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1958)

A type X meets the *Cpp17Swappable* requirements
if lvalues of type X are swappable[.](#swappable.requirements-5.sentence-1)

[6](#swappable.requirements-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1962)

A type X meeting any of the iterator requirements ([[iterator.requirements]](iterator.requirements "24.3 Iterator requirements"))
meets the *Cpp17ValueSwappable* requirements if,
for any dereferenceable objectx of type X,*x is swappable[.](#swappable.requirements-6.sentence-1)

[7](#swappable.requirements-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L1969)

[*Example [1](#swappable.requirements-example-1)*:

User code can ensure that the evaluation of swap calls
is performed in an appropriate context under the various conditions as follows:#include <cassert>#include <utility>// Preconditions: std​::​forward<T>(t) is swappable with std​::​forward<U>(u).template<class T, class U>void value_swap(T&& t, U&& u) {using std::swap;
 swap(std::forward<T>(t), std::forward<U>(u)); // OK, uses âswappable with'' conditions// for rvalues and lvalues}// Preconditions: T meets the [*Cpp17Swappable*](#:Cpp17Swappable "16.4.4.3 Swappable requirements [swappable.requirements]") requirements.template<class T>void lv_swap(T& t1, T& t2) {using std::swap;
 swap(t1, t2); // OK, uses swappable conditions for lvalues of type T}namespace N {struct A { int m; }; struct Proxy { A* a; };
 Proxy proxy(A& a) { return Proxy{ &a }; }void swap(A& x, Proxy p) { std::swap(x.m, p.a->m); // OK, uses context equivalent to swappable// conditions for fundamental types}void swap(Proxy p, A& x) { swap(x, p); } // satisfy symmetry constraint}int main() {int i = 1, j = 2;
 lv_swap(i, j);
 assert(i == 2 && j == 1);

 N::A a1 = { 5 }, a2 = { -5 };
 value_swap(a1, proxy(a2));
 assert(a1.m == -5 && a2.m == 5);}

â *end example*]

#### [16.4.4.4](#nullablepointer.requirements) *Cpp17NullablePointer* requirements [[nullablepointer.requirements]](nullablepointer.requirements)

[1](#nullablepointer.requirements-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2018)

A *Cpp17NullablePointer* type is a pointer-like type that supports null values[.](#nullablepointer.requirements-1.sentence-1)

A type P meets the *Cpp17NullablePointer* requirements if

- [(1.1)](#nullablepointer.requirements-1.1)

P meets the [*Cpp17EqualityComparable*](#:Cpp17EqualityComparable "16.4.4.2 Template argument requirements [utility.arg.requirements]"),[*Cpp17DefaultConstructible*](#:Cpp17DefaultConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]"), [*Cpp17CopyConstructible*](#:Cpp17CopyConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]"), *Cpp17CopyAssignable*,[*Cpp17Swappable*](#:Cpp17Swappable "16.4.4.3 Swappable requirements [swappable.requirements]"), and [*Cpp17Destructible*](#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements,

- [(1.2)](#nullablepointer.requirements-1.2)

the expressions shown in Table [36](#tab:cpp17.nullablepointer "Table 36: Cpp17NullablePointer requirements") are
valid and have the indicated semantics, and

- [(1.3)](#nullablepointer.requirements-1.3)

P meets all the other requirements of this subclause[.](#nullablepointer.requirements-1.sentence-2)

[2](#nullablepointer.requirements-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2032)

A value-initialized object of type P produces the null value of the type[.](#nullablepointer.requirements-2.sentence-1)

The null value shall be equivalent only to itself[.](#nullablepointer.requirements-2.sentence-2)

A default-initialized object
of type P may have an indeterminate or erroneous value[.](#nullablepointer.requirements-2.sentence-3)

[*Note [1](#nullablepointer.requirements-note-1)*:

Operations involving indeterminate values can cause undefined behavior, and
operations involving erroneous values can cause erroneous behavior ([[basic.indet]](basic.indet "6.8.5 Indeterminate and erroneous values"))[.](#nullablepointer.requirements-2.sentence-4)

â *end note*]

[3](#nullablepointer.requirements-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2041)

An object p of type P can be[contextually converted to bool](conv#def:conversion,contextual_to_bool "7.3 Standard conversions [conv]")[.](#nullablepointer.requirements-3.sentence-1)

The effect shall be as if p != nullptr had been evaluated in place of p[.](#nullablepointer.requirements-3.sentence-2)

[4](#nullablepointer.requirements-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2047)

No operation which is part of the *Cpp17NullablePointer* requirements shall exit
via an exception[.](#nullablepointer.requirements-4.sentence-1)

[5](#nullablepointer.requirements-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2051)

In Table [36](#tab:cpp17.nullablepointer "Table 36: Cpp17NullablePointer requirements"), u denotes an identifier, t denotes a non-const lvalue of type P, a and b denote values of type (possibly const) P, and np denotes
a value of type (possibly const) std​::​nullptr_t[.](#nullablepointer.requirements-5.sentence-1)

Table [36](#tab:cpp17.nullablepointer) — *Cpp17NullablePointer* requirements [[tab:cpp17.nullablepointer]](./tab:cpp17.nullablepointer)  

| [ð](#tab:cpp17.nullablepointer-row-1)<br>**Expression** | **Return type** | **Operational semantics** |
| --- | --- | --- |
| [ð](#tab:cpp17.nullablepointer-row-2)<br>P u(np); |  | *Postconditions*: u == nullptr |
| [ð](#tab:cpp17.nullablepointer-row-3)<br>P u = np; |  |  |
| [ð](#tab:cpp17.nullablepointer-row-4)<br>P(np) |  | *Postconditions*: P(np) == nullptr |
| [ð](#tab:cpp17.nullablepointer-row-5)<br>t = np | P& | *Postconditions*: t == nullptr |
| [ð](#tab:cpp17.nullablepointer-row-6)<br>a != b | decltype(a != b) models [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]") | !(a == b) |
| [ð](#tab:cpp17.nullablepointer-row-7)<br>a == np | decltype(a == np) and decltype(np == a) each model [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]") | a == P() |
| [ð](#tab:cpp17.nullablepointer-row-8)<br>np == a |  |  |
| [ð](#tab:cpp17.nullablepointer-row-9)<br>a != np | decltype(a != np) and decltype(np != a) each model [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]") | !(a == np) |
| [ð](#tab:cpp17.nullablepointer-row-10)<br>np != a |  |  |

#### [16.4.4.5](#hash.requirements) *Cpp17Hash* requirements [[hash.requirements]](hash.requirements)

[1](#hash.requirements-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2096)

A type H meets the *Cpp17Hash* requirements if

- [(1.1)](#hash.requirements-1.1)

it is a function object type ([[function.objects]](function.objects "22.10 Function objects")),

- [(1.2)](#hash.requirements-1.2)

it meets the [*Cpp17CopyConstructible*](#:Cpp17CopyConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") (Table [32](#tab:cpp17.copyconstructible "Table 32: Cpp17CopyConstructible requirements (in addition to Cpp17MoveConstructible)")) and [*Cpp17Destructible*](#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") (Table [35](#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements")) requirements, and

- [(1.3)](#hash.requirements-1.3)

the expressions shown in Table [37](#tab:cpp17.hash "Table 37: Cpp17Hash requirements") are valid and have the indicated semantics[.](#hash.requirements-1.sentence-1)

[2](#hash.requirements-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2106)

Given Key is an argument type for function objects of type H, in
Table [37](#tab:cpp17.hash "Table 37: Cpp17Hash requirements") h is a value of type (possibly const) H,u is an lvalue of type Key, and k is a value of a type convertible to
(possibly const) Key[.](#hash.requirements-2.sentence-1)

Table [37](#tab:cpp17.hash) — *Cpp17Hash* requirements [[tab:cpp17.hash]](./tab:cpp17.hash)  

| [ð](#tab:cpp17.hash-row-1)<br>**Expression** | **Return type** | **Requirement** |
| --- | --- | --- |
| [ð](#tab:cpp17.hash-row-2)<br>h(k) | size_t | The value returned shall depend only on the argument k for the duration of  the program[.](#tab:cpp17.hash-row-2-column-3-sentence-1)<br>[*Note [1](#tab:cpp17.hash-row-2-column-3-note-1)*:<br>Thus all evaluations of the expression h(k) with the  same value for k yield the same result for a given execution of the program[.](#tab:cpp17.hash-row-2-column-3-sentence-2) â *end note*]<br>  For two different  values t1 and t2, the probability that h(t1) and h(t2)  compare equal should be very small, approaching 1.0 / numeric_limits<size_t>​::​max()[.](#tab:cpp17.hash-row-2-column-3-sentence-3) |
| [ð](#tab:cpp17.hash-row-3)<br>h(u) | size_t | Shall not modify u[.](#tab:cpp17.hash-row-3-column-3-sentence-1) |

#### [16.4.4.6](#allocator.requirements) *Cpp17Allocator* requirements [[allocator.requirements]](allocator.requirements)

#### [16.4.4.6.1](#allocator.requirements.general) General [[allocator.requirements.general]](allocator.requirements.general)

[1](#allocator.requirements.general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2138)

The library describes a standard set of requirements for [*allocators*](#def:allocators),
which are class-type objects that encapsulate the information about an allocation model[.](#allocator.requirements.general-1.sentence-1)

This information includes the knowledge of pointer types, the type of their
difference, the type of the size of objects in this allocation model, as well
as the memory allocation and deallocation primitives for it[.](#allocator.requirements.general-1.sentence-2)

All of the
string types ([[strings]](strings "27 Strings library")),
containers ([[containers]](containers "23 Containers library")) (except array and inplace_vector),
string buffers and string streams ([[input.output]](input.output "31 Input/output library")), and[match_results](re "28.6 Regular expressions library [re]") are parameterized in terms of
allocators[.](#allocator.requirements.general-1.sentence-3)

[2](#allocator.requirements.general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2150)

In [[allocator.requirements]](#allocator.requirements "16.4.4.6 Cpp17Allocator requirements"),

- [(2.1)](#allocator.requirements.general-2.1)

T, U, C denote
any cv-unqualified object type ([[basic.types.general]](basic.types.general#term.object.type "6.9.1 General")),

- [(2.2)](#allocator.requirements.general-2.2)

X denotes an allocator class for type T,

- [(2.3)](#allocator.requirements.general-2.3)

Y denotes the corresponding allocator class for type U,

- [(2.4)](#allocator.requirements.general-2.4)

XX denotes the type allocator_traits<X>,

- [(2.5)](#allocator.requirements.general-2.5)

YY denotes the type allocator_traits<Y>,

- [(2.6)](#allocator.requirements.general-2.6)

a, a1, a2 denote lvalues of type X,

- [(2.7)](#allocator.requirements.general-2.7)

u denotes the name of a variable being declared,

- [(2.8)](#allocator.requirements.general-2.8)

b denotes a value of type Y,

- [(2.9)](#allocator.requirements.general-2.9)

c denotes a pointer of type C* through which indirection is valid,

- [(2.10)](#allocator.requirements.general-2.10)

p denotes a value of type XX​::​pointer obtained by calling a1.allocate, where a1 == a,

- [(2.11)](#allocator.requirements.general-2.11)

q denotes a value of type XX​::​const_pointer obtained by conversion from a value p,

- [(2.12)](#allocator.requirements.general-2.12)

r denotes a value of type T& obtained by the expression *p,

- [(2.13)](#allocator.requirements.general-2.13)

w denotes a value of type XX​::​void_pointer obtained by conversion from a value p,

- [(2.14)](#allocator.requirements.general-2.14)

x denotes a value of type XX​::​const_void_pointer obtained by conversion from a value q or a value w,

- [(2.15)](#allocator.requirements.general-2.15)

y denotes a value of type XX​::​const_void_pointer obtained by conversion from a result value of YY​::​allocate, or else
a value of type (possibly const) std​::​nullptr_t,

- [(2.16)](#allocator.requirements.general-2.16)

n denotes a value of type XX​::​size_type,

- [(2.17)](#allocator.requirements.general-2.17)

Args denotes a template parameter pack, and

- [(2.18)](#allocator.requirements.general-2.18)

args denotes
a function parameter pack with the pattern Args&&[.](#allocator.requirements.general-2.sentence-1)

[3](#allocator.requirements.general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2201)

The class template allocator_traits ([[allocator.traits]](allocator.traits "20.2.9 Allocator traits")) supplies
a uniform interface to all allocator types[.](#allocator.requirements.general-3.sentence-1)

This subclause
describes the requirements on allocator types
and thus on types used to instantiate allocator_traits[.](#allocator.requirements.general-3.sentence-2)

A requirement is optional if a default for a
given type or expression is specified[.](#allocator.requirements.general-3.sentence-3)

Within the standard library allocator_traits template, an optional requirement that is not supplied by an allocator is
replaced by the specified default type or expression[.](#allocator.requirements.general-3.sentence-4)

[*Note [1](#allocator.requirements.general-note-1)*:

There are no program-defined specializations of allocator_traits[.](#allocator.requirements.general-3.sentence-5)

â *end note*]

[ð](#allocator.requirements.general-itemdecl:1)

`typename X::pointer
`

[4](#allocator.requirements.general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2221)

*Remarks*: Default: T*

[ð](#allocator.requirements.general-itemdecl:2)

`typename X::const_pointer
`

[5](#allocator.requirements.general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2231)

*Mandates*: XX​::​pointer is convertible to XX​::​const_pointer[.](#allocator.requirements.general-5.sentence-1)

[6](#allocator.requirements.general-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2235)

*Remarks*: Default: pointer_traits<XX​::​pointer>​::​rebind<const T>

[ð](#allocator.requirements.general-itemdecl:3)

`typename X::void_pointer
typename Y::void_pointer
`

[7](#allocator.requirements.general-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2246)

*Mandates*: XX​::​pointer is convertible to XX​::​void_pointer[.](#allocator.requirements.general-7.sentence-1)

XX​::​void_pointer and YY​::​void_pointer are the same type[.](#allocator.requirements.general-7.sentence-2)

[8](#allocator.requirements.general-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2251)

*Remarks*: Default:pointer_traits<XX​::​pointer>​::​rebind<void>

[ð](#allocator.requirements.general-itemdecl:4)

`typename X::const_void_pointer
typename Y::const_void_pointer
`

[9](#allocator.requirements.general-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2263)

*Mandates*: XX​::​pointer, XX​::​const_pointer, and XX​::​void_pointer are convertible to XX​::​const_void_pointer[.](#allocator.requirements.general-9.sentence-1)

XX​::​const_void_pointer and YY​::​const_void_pointer are the same type[.](#allocator.requirements.general-9.sentence-2)

[10](#allocator.requirements.general-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2270)

*Remarks*: Default:pointer_traits<XX​::​pointer>​::​rebind<const void>

[ð](#allocator.requirements.general-itemdecl:5)

`typename X::value_type
`

[11](#allocator.requirements.general-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2281)

*Result*: Identical to T[.](#allocator.requirements.general-11.sentence-1)

[ð](#allocator.requirements.general-itemdecl:6)

`typename X::size_type
`

[12](#allocator.requirements.general-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2291)

*Result*: An unsigned integer type
that can represent the size of the largest object in the allocation model[.](#allocator.requirements.general-12.sentence-1)

[13](#allocator.requirements.general-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2296)

*Remarks*: Default:make_unsigned_t<XX​::​difference_type>

[ð](#allocator.requirements.general-itemdecl:7)

`typename X::difference_type
`

[14](#allocator.requirements.general-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2307)

*Result*: A signed integer type that can represent
the difference between any two pointers in the allocation model[.](#allocator.requirements.general-14.sentence-1)

[15](#allocator.requirements.general-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2312)

*Remarks*: Default:pointer_traits<XX​::​pointer>​::​difference_type

[ð](#allocator.requirements.general-itemdecl:8)

`typename X::rebind<U>::other
`

[16](#allocator.requirements.general-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2323)

*Result*: Y

[17](#allocator.requirements.general-17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2327)

*Postconditions*: For all U (including T),YY​::​rebind_alloc<T> is X[.](#allocator.requirements.general-17.sentence-1)

[18](#allocator.requirements.general-18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2332)

*Remarks*: If Allocator is a class template instantiation of the formSomeAllocator<T, Args>, where Args is zero or more type
arguments, and Allocator does not supply a rebind member
template, the standard allocator_traits template usesSomeAllocator<U, Args> in place of Allocator​::​rebind<U>​::​other by default[.](#allocator.requirements.general-18.sentence-1)

For allocator types that are not template instantiations of the
above form, no default is provided[.](#allocator.requirements.general-18.sentence-2)

[19](#allocator.requirements.general-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2342)

[*Note [2](#allocator.requirements.general-note-2)*:

The member class template rebind of X is
effectively a typedef template[.](#allocator.requirements.general-19.sentence-1)

In general, if
the name Allocator is bound to SomeAllocator<T>, thenAllocator​::​rebind<U>​::​other is the same type asSomeAllocator<U>, whereSomeAllocator<T>​::​value_type is T andSomeAllocator<U>​::​value_type is U[.](#allocator.requirements.general-19.sentence-2)

â *end note*]

[ð](#allocator.requirements.general-itemdecl:9)

`*p
`

[20](#allocator.requirements.general-20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2360)

*Result*: T&

[ð](#allocator.requirements.general-itemdecl:10)

`*q
`

[21](#allocator.requirements.general-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2370)

*Result*: const T&

[22](#allocator.requirements.general-22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2374)

*Postconditions*: *q refers to the same object as *p[.](#allocator.requirements.general-22.sentence-1)

[ð](#allocator.requirements.general-itemdecl:11)

`p->m
`

[23](#allocator.requirements.general-23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2384)

*Result*: Type of T​::​m[.](#allocator.requirements.general-23.sentence-1)

[24](#allocator.requirements.general-24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2388)

*Preconditions*: (*p).m is well-defined[.](#allocator.requirements.general-24.sentence-1)

[25](#allocator.requirements.general-25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2392)

*Effects*: Equivalent to (*p).m[.](#allocator.requirements.general-25.sentence-1)

[ð](#allocator.requirements.general-itemdecl:12)

`q->m
`

[26](#allocator.requirements.general-26)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2402)

*Result*: Type of T​::​m[.](#allocator.requirements.general-26.sentence-1)

[27](#allocator.requirements.general-27)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2406)

*Preconditions*: (*q).m is well-defined[.](#allocator.requirements.general-27.sentence-1)

[28](#allocator.requirements.general-28)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2410)

*Effects*: Equivalent to (*q).m[.](#allocator.requirements.general-28.sentence-1)

[ð](#allocator.requirements.general-itemdecl:13)

`static_cast<XX::pointer>(w)
`

[29](#allocator.requirements.general-29)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2420)

*Result*: XX​::​pointer

[30](#allocator.requirements.general-30)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2424)

*Postconditions*: static_cast<XX​::​pointer>(w) == p[.](#allocator.requirements.general-30.sentence-1)

[ð](#allocator.requirements.general-itemdecl:14)

`static_cast<XX::const_pointer>(x)
`

[31](#allocator.requirements.general-31)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2434)

*Result*: XX​::​const_pointer

[32](#allocator.requirements.general-32)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2438)

*Postconditions*: static_cast<XX​::​const_pointer>(x) == q[.](#allocator.requirements.general-32.sentence-1)

[ð](#allocator.requirements.general-itemdecl:15)

`pointer_traits<XX::pointer>::pointer_to(r)
`

[33](#allocator.requirements.general-33)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2448)

*Result*: XX​::​pointer

[34](#allocator.requirements.general-34)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2452)

*Postconditions*: Same as p[.](#allocator.requirements.general-34.sentence-1)

[ð](#allocator.requirements.general-itemdecl:16)

`a.allocate(n)
`

[35](#allocator.requirements.general-35)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2462)

*Result*: XX​::​pointer

[36](#allocator.requirements.general-36)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2466)

*Effects*: Memory is allocated for an array of n T and such an object is created
but array elements are not constructed[.](#allocator.requirements.general-36.sentence-1)

[*Example [1](#allocator.requirements.general-example-1)*:

When reusing storage denoted by some pointer value p,launder(reinterpret_cast<T*>(new (p) byte[n * sizeof(T)])) can be used to implicitly create a suitable array object
and obtain a pointer to it[.](#allocator.requirements.general-36.sentence-2)

â *end example*]

[37](#allocator.requirements.general-37)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2478)

*Throws*: allocate may throw an appropriate exception[.](#allocator.requirements.general-37.sentence-1)

[38](#allocator.requirements.general-38)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2482)

[*Note [3](#allocator.requirements.general-note-3)*:

It is intended that a.allocate be an efficient means
of allocating a single object of type T, even when sizeof(T) is small[.](#allocator.requirements.general-38.sentence-1)

That is, there is no need for a container to maintain its own
free list[.](#allocator.requirements.general-38.sentence-2)

â *end note*]

[39](#allocator.requirements.general-39)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2490)

*Remarks*: If n == 0, the return value is unspecified[.](#allocator.requirements.general-39.sentence-1)

[ð](#allocator.requirements.general-itemdecl:17)

`a.allocate(n, y)
`

[40](#allocator.requirements.general-40)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2500)

*Result*: XX​::​pointer

[41](#allocator.requirements.general-41)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2504)

*Effects*: Same as a.allocate(n)[.](#allocator.requirements.general-41.sentence-1)

The use of y is unspecified, but it is intended as an aid to locality[.](#allocator.requirements.general-41.sentence-2)

[42](#allocator.requirements.general-42)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2509)

*Remarks*: Default: a.allocate(n)

[ð](#allocator.requirements.general-itemdecl:18)

`a.allocate_at_least(n)
`

[43](#allocator.requirements.general-43)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2519)

*Result*: allocation_result<XX​::​pointer, XX​::​size_type>

[44](#allocator.requirements.general-44)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2523)

*Returns*: allocation_result<XX​::​pointer, XX​::​size_type>{ptr, count} where ptr is memory allocated for an array of count T and such an object is created but array elements are not constructed,
such that count â¥ n[.](#allocator.requirements.general-44.sentence-1)

If n == 0, the return value is unspecified[.](#allocator.requirements.general-44.sentence-2)

[45](#allocator.requirements.general-45)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2531)

*Throws*: allocate_at_least may throw an appropriate exception[.](#allocator.requirements.general-45.sentence-1)

[46](#allocator.requirements.general-46)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2535)

*Remarks*: Default: {a.allocate(n), n}[.](#allocator.requirements.general-46.sentence-1)

[ð](#allocator.requirements.general-itemdecl:19)

`a.deallocate(p, n)
`

[47](#allocator.requirements.general-47)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2545)

*Result*: (not used)

[48](#allocator.requirements.general-48)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2549)

*Preconditions*: 

- [(48.1)](#allocator.requirements.general-48.1)

  If p is memory
that was obtained by a call to a.allocate_at_least,
let ret be the value returned andreq be the value passed as the first argument of that call[.](#allocator.requirements.general-48.1.sentence-1)
  p is equal to ret.ptr andn is a value such thatreq â¤ n â¤ ret.count[.](#allocator.requirements.general-48.1.sentence-2)

- [(48.2)](#allocator.requirements.general-48.2)

  Otherwise, p is a pointer value obtained from allocate[.](#allocator.requirements.general-48.2.sentence-1)
  n equals the value passed as the first argument
to the invocation of allocate which returned p[.](#allocator.requirements.general-48.2.sentence-2)

p has not been invalidated by
an intervening call to deallocate[.](#allocator.requirements.general-48.sentence-2)

[49](#allocator.requirements.general-49)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2568)

*Throws*: Nothing[.](#allocator.requirements.general-49.sentence-1)

[ð](#allocator.requirements.general-itemdecl:20)

`a.max_size()
`

[50](#allocator.requirements.general-50)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2578)

*Result*: XX​::​size_type

[51](#allocator.requirements.general-51)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2582)

*Returns*: The largest value n that can meaningfully be passed to a.allocate(n)[.](#allocator.requirements.general-51.sentence-1)

[52](#allocator.requirements.general-52)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2586)

*Remarks*: Default:numeric_limits<size_type>​::​max() / sizeof(value_type)

[ð](#allocator.requirements.general-itemdecl:21)

`a1 == a2
`

[53](#allocator.requirements.general-53)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2597)

*Result*: bool

[54](#allocator.requirements.general-54)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2601)

*Returns*: true only if storage allocated from each can
be deallocated via the other[.](#allocator.requirements.general-54.sentence-1)

[55](#allocator.requirements.general-55)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2606)

*Throws*: Nothing[.](#allocator.requirements.general-55.sentence-1)

[56](#allocator.requirements.general-56)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2610)

*Remarks*: operator== shall be reflexive, symmetric,
and transitive[.](#allocator.requirements.general-56.sentence-1)

[ð](#allocator.requirements.general-itemdecl:22)

`a1 != a2
`

[57](#allocator.requirements.general-57)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2621)

*Result*: bool

[58](#allocator.requirements.general-58)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2625)

*Returns*: !(a1 == a2)[.](#allocator.requirements.general-58.sentence-1)

[ð](#allocator.requirements.general-itemdecl:23)

`a == b
`

[59](#allocator.requirements.general-59)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2635)

*Result*: bool

[60](#allocator.requirements.general-60)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2639)

*Returns*: a == YY​::​rebind_alloc<T>(b)[.](#allocator.requirements.general-60.sentence-1)

[ð](#allocator.requirements.general-itemdecl:24)

`a != b
`

[61](#allocator.requirements.general-61)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2649)

*Result*: bool

[62](#allocator.requirements.general-62)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2653)

*Returns*: !(a == b)[.](#allocator.requirements.general-62.sentence-1)

[ð](#allocator.requirements.general-itemdecl:25)

`X u(a);
X u = a;
`

[63](#allocator.requirements.general-63)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2664)

*Postconditions*: u == a

[64](#allocator.requirements.general-64)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2668)

*Throws*: Nothing[.](#allocator.requirements.general-64.sentence-1)

[ð](#allocator.requirements.general-itemdecl:26)

`X u(b);
`

[65](#allocator.requirements.general-65)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2678)

*Postconditions*: Y(u) == b and u == X(b)[.](#allocator.requirements.general-65.sentence-1)

[66](#allocator.requirements.general-66)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2682)

*Throws*: Nothing[.](#allocator.requirements.general-66.sentence-1)

[ð](#allocator.requirements.general-itemdecl:27)

`X u(std::move(a));
X u = std::move(a);
`

[67](#allocator.requirements.general-67)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2693)

*Postconditions*: The value of a is unchanged and is equal to u[.](#allocator.requirements.general-67.sentence-1)

[68](#allocator.requirements.general-68)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2697)

*Throws*: Nothing[.](#allocator.requirements.general-68.sentence-1)

[ð](#allocator.requirements.general-itemdecl:28)

`X u(std::move(b));
`

[69](#allocator.requirements.general-69)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2707)

*Postconditions*: u is equal to the prior value of X(b)[.](#allocator.requirements.general-69.sentence-1)

[70](#allocator.requirements.general-70)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2711)

*Throws*: Nothing[.](#allocator.requirements.general-70.sentence-1)

[ð](#allocator.requirements.general-itemdecl:29)

`a.construct(c, args...)
`

[71](#allocator.requirements.general-71)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2721)

*Result*: (not used)

[72](#allocator.requirements.general-72)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2725)

*Effects*: Constructs an object of type C at c[.](#allocator.requirements.general-72.sentence-1)

[73](#allocator.requirements.general-73)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2729)

*Remarks*: Default:construct_at(c, std​::​forward<Args>(args)...)

[ð](#allocator.requirements.general-itemdecl:30)

`a.destroy(c)
`

[74](#allocator.requirements.general-74)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2740)

*Result*: (not used)

[75](#allocator.requirements.general-75)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2744)

*Effects*: Destroys the object at c[.](#allocator.requirements.general-75.sentence-1)

[76](#allocator.requirements.general-76)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2748)

*Remarks*: Default: destroy_at(c)

[ð](#allocator.requirements.general-itemdecl:31)

`a.select_on_container_copy_construction()
`

[77](#allocator.requirements.general-77)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2758)

*Result*: X

[78](#allocator.requirements.general-78)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2762)

*Returns*: Typically returns either a or X()[.](#allocator.requirements.general-78.sentence-1)

[79](#allocator.requirements.general-79)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2766)

*Remarks*: Default: return a;

[ð](#allocator.requirements.general-itemdecl:32)

`typename X::propagate_on_container_copy_assignment
`

[80](#allocator.requirements.general-80)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2776)

*Result*: Identical to or derived from true_type or false_type[.](#allocator.requirements.general-80.sentence-1)

[81](#allocator.requirements.general-81)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2780)

*Returns*: true_type only if an allocator of type X should be copied
when the client container is copy-assigned;
if so, X shall meet
the [*Cpp17CopyAssignable*](#:Cpp17CopyAssignable "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements (Table [34](#tab:cpp17.copyassignable "Table 34: Cpp17CopyAssignable requirements (in addition to Cpp17MoveAssignable)")) and
the copy operation shall not throw exceptions[.](#allocator.requirements.general-81.sentence-1)

[82](#allocator.requirements.general-82)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2788)

*Remarks*: Default: false_type

[ð](#allocator.requirements.general-itemdecl:33)

`typename X::propagate_on_container_move_assignment
`

[83](#allocator.requirements.general-83)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2798)

*Result*: Identical to or derived from true_type or false_type[.](#allocator.requirements.general-83.sentence-1)

[84](#allocator.requirements.general-84)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2802)

*Returns*: true_type only if an allocator of type X should be moved
when the client container is move-assigned;
if so, X shall meet
the [*Cpp17MoveAssignable*](#:Cpp17MoveAssignable "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements (Table [33](#tab:cpp17.moveassignable "Table 33: Cpp17MoveAssignable requirements")) and
the move operation shall not throw exceptions[.](#allocator.requirements.general-84.sentence-1)

[85](#allocator.requirements.general-85)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2810)

*Remarks*: Default: false_type

[ð](#allocator.requirements.general-itemdecl:34)

`typename X::propagate_on_container_swap
`

[86](#allocator.requirements.general-86)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2820)

*Result*: Identical to or derived from true_type or false_type[.](#allocator.requirements.general-86.sentence-1)

[87](#allocator.requirements.general-87)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2824)

*Returns*: true_type only if an allocator of type X should be swapped
when the client container is swapped;
if so,X shall meet the [*Cpp17Swappable*](#:Cpp17Swappable "16.4.4.3 Swappable requirements [swappable.requirements]") requirements ([[swappable.requirements]](#swappable.requirements "16.4.4.3 Swappable requirements")) and
the swap operation shall not throw exceptions[.](#allocator.requirements.general-87.sentence-1)

[88](#allocator.requirements.general-88)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2832)

*Remarks*: Default: false_type

[ð](#allocator.requirements.general-itemdecl:35)

`typename X::is_always_equal
`

[89](#allocator.requirements.general-89)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2842)

*Result*: Identical to or derived from true_type or false_type[.](#allocator.requirements.general-89.sentence-1)

[90](#allocator.requirements.general-90)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2846)

*Returns*: true_type only if the expression a1 == a2 is guaranteed
to be true for any two (possibly const) valuesa1, a2 of type X[.](#allocator.requirements.general-90.sentence-1)

[91](#allocator.requirements.general-91)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2852)

*Remarks*: Default: is_empty<X>​::​type

[92](#allocator.requirements.general-92)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2857)

An allocator type X shall meet the[*Cpp17CopyConstructible*](#:Cpp17CopyConstructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements (Table [32](#tab:cpp17.copyconstructible "Table 32: Cpp17CopyConstructible requirements (in addition to Cpp17MoveConstructible)"))[.](#allocator.requirements.general-92.sentence-1)

The XX​::​pointer, XX​::​const_pointer, XX​::​void_pointer, andXX​::​const_void_pointer types shall meet the*Cpp17NullablePointer* requirements (Table [36](#tab:cpp17.nullablepointer "Table 36: Cpp17NullablePointer requirements"))[.](#allocator.requirements.general-92.sentence-2)

No constructor,
comparison operator function, copy operation, move operation, or swap operation on
these pointer types shall exit via an exception[.](#allocator.requirements.general-92.sentence-3)

XX​::​pointer and XX​::​const_pointer shall also
meet the requirements for
a [*Cpp17RandomAccessIterator*](random.access.iterators#:Cpp17RandomAccessIterator "24.3.5.7 Random access iterators [random.access.iterators]") ([[random.access.iterators]](random.access.iterators "24.3.5.7 Random access iterators")) and
the additional requirement that, when p and (p + n) are
dereferenceable pointer values for some integral value n,addressof(*(p + n)) == addressof(*p) + n is true[.](#allocator.requirements.general-92.sentence-4)

[93](#allocator.requirements.general-93)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2875)

Let x1 and x2 denote objects of (possibly different) typesXX​::​void_pointer, XX​::​const_void_pointer, XX​::​pointer,
or XX​::​const_pointer[.](#allocator.requirements.general-93.sentence-1)

Then, x1 and x2 are[*equivalently-valued*](#def:equivalently-valued "16.4.4.6.1 General [allocator.requirements.general]") pointer values, if and only if both x1 and x2 can be explicitly converted to the two corresponding objects px1 and px2 of type XX​::​const_pointer, using a sequence of static_casts
using only these four types, and the expression px1 == px2 evaluates to true[.](#allocator.requirements.general-93.sentence-2)

[94](#allocator.requirements.general-94)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2885)

Let w1 and w2 denote objects of type XX​::​void_pointer[.](#allocator.requirements.general-94.sentence-1)

Then for the expressionsw1 == w2
w1 != w2 either or both objects may be replaced by an equivalently-valued object of typeXX​::​const_void_pointer with no change in semantics[.](#allocator.requirements.general-94.sentence-2)

[95](#allocator.requirements.general-95)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2895)

Let p1 and p2 denote objects of type XX​::​pointer[.](#allocator.requirements.general-95.sentence-1)

Then for the expressionsp1 == p2
p1 != p2
p1 < p2
p1 <= p2
p1 >= p2
p1 > p2
p1 - p2 either or both objects may be replaced by an equivalently-valued object of typeXX​::​const_pointer with no change in semantics[.](#allocator.requirements.general-95.sentence-2)

[96](#allocator.requirements.general-96)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2910)

An allocator may constrain the types on which it can be instantiated and the
arguments for which its construct or destroy members may be
called[.](#allocator.requirements.general-96.sentence-1)

If a type cannot be used with a particular allocator, the allocator
class or the call to construct or destroy may fail to instantiate[.](#allocator.requirements.general-96.sentence-2)

[97](#allocator.requirements.general-97)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2916)

If the alignment associated with a specific over-aligned type is not
supported by an allocator, instantiation of the allocator for that type may
fail[.](#allocator.requirements.general-97.sentence-1)

The allocator also may silently ignore the requested alignment[.](#allocator.requirements.general-97.sentence-2)

[*Note [4](#allocator.requirements.general-note-4)*:

Additionally, the member function allocate for that type can fail by throwing an object of typebad_alloc[.](#allocator.requirements.general-97.sentence-3)

â *end note*]

[98](#allocator.requirements.general-98)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2926)

[*Example [2](#allocator.requirements.general-example-2)*:

The following is an allocator class template supporting the minimal
interface that meets the requirements of [[allocator.requirements.general]](#allocator.requirements.general "16.4.4.6.1 General"):template<class T>struct SimpleAllocator {using value_type = T;
 SimpleAllocator(*ctor args*); template<class U> SimpleAllocator(const SimpleAllocator<U>& other);

 T* allocate(std::size_t n); void deallocate(T* p, std::size_t n); template<class U> bool operator==(const SimpleAllocator<U>& rhs) const;};

â *end example*]

[99](#allocator.requirements.general-99)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/lib-intro.tex#L2946)

The following exposition-only concept defines
the minimal requirements on an Allocator type[.](#allocator.requirements.general-99.sentence-1)

template<class Alloc>concept [*simple-allocator*](#concept:simple-allocator "16.4.4.6.1 General [allocator.requirements.general]") =requires(Alloc alloc, size_t n) {{ *alloc.allocate(n) } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<typename Alloc::value_type&>; { alloc.deallocate(alloc.allocate(n), n) }; } &&[copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_­constructible [concept.copyconstructible]")<Alloc> &&[equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<Alloc>;

A type Alloc models [*simple-allocator*](#concept:simple-allocator "16.4.4.6.1 General [allocator.requirements.general]") if it meets the requirements of [[allocator.requirements.general]](#allocator.requirements.general "16.4.4.6.1 General")[.](#allocator.requirements.general-99.sentence-2)

#### [16.4.4.6.2](#allocator.requirements.completeness) Allocator completeness requirements [[allocator.requirements.completeness]](allocator.requirements.completeness)

[1](#allocator.requirements.completeness-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)](#allocator.requirements.completeness-1.1)

X is a complete type, and

- [(1.2)](#allocator.requirements.completeness-1.2)

all the member types of [allocator_traits<X>](allocator.traits "20.2.9 Allocator traits [allocator.traits]") other than value_type are complete types[.](#allocator.requirements.completeness-1.sentence-1)
