All of the containers defined in [containers] and in [basic.string] except array
meet the additional requirements of an *allocator-aware container*,
as described below.

Given an allocator type A
and given a container type X having a value_type identical to T
and an allocator_type identical to allocator_traits<A>::rebind_alloc<T>
and given an lvalue m of type A,
a pointer p of type T*,
an expression v of type T or const T,
and an rvalue rv of type T,
the following terms are defined.

If X
is not allocator-aware or is a specialization of basic_string,
the terms below are defined as if A were
allocator<T> — no allocator object needs to be created
and user specializations of allocator<T> are not instantiated:

- T is
means that the following expression is well-formed: allocator_traits<A>::construct(m, p)*Cpp17DefaultInsertable*into X - An element of X is
*default-inserted*if it is initialized by evaluation of the expression allocator_traits<A>::construct(m, p) where p is the address of the uninitialized storage for the element allocated within X. - T is
means that the following expression is well-formed: allocator_traits<A>::construct(m, p, rv) and its evaluation causes the following postcondition to hold: The value of *p is equivalent to the value of rv before the evaluation.*Cpp17MoveInsertable*into X - T is
means that, in addition to T being*Cpp17CopyInsertable*into X*Cpp17MoveInsertable*into X, the following expression is well-formed: allocator_traits<A>::construct(m, p, v) and its evaluation causes the following postcondition to hold: The value of v is unchanged and is equivalent to *p. - T is
, for zero or more arguments args, means that the following expression is well-formed: allocator_traits<A>::construct(m, p, args)*Cpp17EmplaceConstructible*into X from args - T is
means that the following expression is well-formed: allocator_traits<A>::destroy(m, p)*Cpp17Erasable*from X

The following exposition-only concept is used in the definition of containers:
template<class R, class T>
concept *container-compatible-range* = // *exposition only*
ranges::input_range<R> && convertible_to<ranges::range_reference_t<R>, T>;

In this subclause,

- X denotes an allocator-aware container class with a value_type of T using an allocator of type A,
- u denotes a variable,
- a and b denote non-const lvalues of type X,
- c denotes an lvalue of type const X,
- t denotes an lvalue or a const rvalue of type X,
- rv denotes a non-const rvalue of type X, and
- m is a value of type A.

A type X meets the allocator-aware container requirements
if X meets the container requirements and
the following types, statements, and expressions are well-formed and have
the specified semantics.

```
typename X::allocator_type
```

```
c.get_allocator()
```

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

```
X u(m);
```

```
X u(t, m);
```

```
X u(rv);
```

```
X u(rv, m);
```

```
a = t
```

```
a = rv
```

```
a.swap(b)
```

The behavior of certain container member functions and deduction guides
depends on whether types qualify as input iterators or allocators.

The extent to which an implementation determines that a type cannot be an input
iterator is unspecified, except that as a minimum integral types shall not qualify
as input iterators.

Likewise, the extent to which an implementation determines that a type cannot be
an allocator is unspecified, except that as a minimum a type A shall not qualify
as an allocator unless it meets both of the following conditions:

- The expression declval<A&>().allocate(size_t{}) is well-formed when treated as an unevaluated operand.