23 Containers library [containers]

23.2 Requirements [container.requirements]

23.2.2 General containers [container.requirements.general]

23.2.2.5 Allocator-aware containers [container.alloc.reqmts]

Except for array and inplace_vector, all of the containers defined in [containers], [stacktrace.basic], [basic.string], and [re.results] 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 that denotes an lvalue of type T or const T or an rvalue of type 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 Cpp17DefaultInsertable into X means that the following expression is well-formed: allocator_traits<A>::construct(m, p)
  • 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 Cpp17MoveInsertable into X 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.
    [Note 1: 
    rv remains a valid object.
    Its state is unspecified.
    — end note]
  • T is Cpp17CopyInsertable into X means that, in addition to T being 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 Cpp17EmplaceConstructible into X from args, for zero or more arguments args, means that the following expression is well-formed: allocator_traits<A>::construct(m, p, args)
  • T is Cpp17Erasable from X means that the following expression is well-formed: allocator_traits<A>::destroy(m, p)
[Note 2: 
A container calls allocator_traits<A>​::​construct(m, p, args) to construct an element at p using args, with m == get_allocator().
The default construct in allocator will call ​::​new((void*)p) T(args), but specialized allocators can choose a different definition.
— end note]
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
Result: A
Mandates: allocator_type​::​value_type is the same as X​::​value_type.
c.get_allocator()
Result: A
Complexity: Constant.
X u; X u = X();
Preconditions: A meets the Cpp17DefaultConstructible requirements.
Postconditions: u.empty() returns true, u.get_allocator() == A().
Complexity: Constant.
X u(m);
Postconditions: u.empty() returns true, u.get_allocator() == m.
Complexity: Constant.
X u(t, m);
Preconditions: T is Cpp17CopyInsertable into X.
Postconditions: u == t, u.get_allocator() == m
Complexity: Linear.
X u(rv);
Postconditions: u has the same elements as rv had before this construction; the value of u.get_allocator() is the same as the value of rv.get_allocator() before this construction.
Complexity: Constant.
X u(rv, m);
Preconditions: T is Cpp17MoveInsertable into X.
Postconditions: u has the same elements, or copies of the elements, that rv had before this construction, u.get_allocator() == m.
Complexity: Constant if m == rv.get_allocator(), otherwise linear.
a = t
Result: X&.
Preconditions: T is Cpp17CopyInsertable into X and Cpp17CopyAssignable.
Postconditions: a == t is true.
Complexity: Linear.
a = rv
Result: X&.
Preconditions: If allocator_traits<allocator_type>​::​propagate_on_container_move_assignment​::​value is false, T is Cpp17MoveInsertable into X and Cpp17MoveAssignable.
Effects: All existing elements of a are either move assigned to or destroyed.
Postconditions: If a and rv do not refer to the same object, a is equal to the value that rv had before this assignment.
Complexity: Linear.
a.swap(b)
Result: void
Effects: Exchanges the contents of a and b.
Complexity: Constant.