The library describes a standard set of requirements for allocators, which are class-type objects that encapsulate the information about an allocation model. 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. All of the string types (Clause [strings]), containers (Clause [containers]) (except array), string buffers and string streams (Clause [input.output]), and match_results (Clause [re]) are parameterized in terms of allocators.
The template struct allocator_traits ([allocator.traits]) supplies a uniform interface to all allocator types. Table [tab:desc.var.def] describes the types manipulated through allocators. Table [tab:utilities.allocator.requirements] describes the requirements on allocator types and thus on types used to instantiate allocator_traits. A requirement is optional if the last column of Table [tab:utilities.allocator.requirements] specifies a default for a given expression. Within the standard library allocator_traits template, an optional requirement that is not supplied by an allocator is replaced by the specified default expression. A user specialization of allocator_traits may provide different defaults and may provide defaults for different requirements than the primary template. Within Tables [tab:desc.var.def] and [tab:utilities.allocator.requirements], the use of move and forward always refers to std::move and std::forward, respectively.
Variable | Definition |
T, U, C | any non-const object type ([basic.types]) |
V | a type convertible to T |
X | an Allocator class for type T |
Y | the corresponding Allocator class for type U |
XX | the type allocator_traits<X> |
YY | the type allocator_traits<Y> |
t | a value of type const T& |
a, a1, a2 | values of type X& |
a3 | an rvalue of type X |
b | a value of type Y |
c | a pointer of type C* through which indirection is valid |
p | a value of type XX::pointer, obtained by calling a1.allocate, where a1 == a |
q | a value of type XX::const_pointer obtained by conversion from a value p. |
w | a value of type XX::void_pointer obtained by conversion from a value p |
z | a value of type XX::const_void_pointer obtained by conversion from a value q or a value w |
r | a value of type T& obtained by the expression *p. |
s | a value of type const T& obtained by the expression *q or by conversion from a value r. |
u | 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. |
v | a value of type V |
n | a value of type XX::size_type. |
Args | a template parameter pack |
args | a function parameter pack with the pattern Args&& |
Expression | Return type | Assertion/note | Default |
pre-/post-condition | |||
X::pointer | T* | ||
X::const_pointer | X::pointer is convertible to X::const_pointer | pointer_traits<X::pointer>::rebind<const T> | |
X::void_pointer Y::void_pointer | X::pointer is convertible to X::void_pointer. X::void_pointer and Y::void_pointer are the same type. | pointer_traits<X::pointer>::rebind<void> | |
X::const_void_pointer Y::const_void_pointer | X::pointer, X::const_pointer, and X::void_pointer are convertible to X::const_void_pointer. X::const_void_pointer and Y::const_void_pointer are the same type. | pointer_traits<X::pointer>::rebind<const void> | |
X::value_type | Identical to T | ||
X::size_type | unsigned integer type | a type that can represent the size of the largest object in the allocation model. | make_unsigned_t<X::difference_type> |
X::difference_type | signed integer type | a type that can represent the difference between any two pointers in the allocation model. | pointer_traits<X::pointer>::difference_type |
typename X::template rebind<U>::other | Y | For all U (including T), Y::template rebind<T>::other is X. | See Note A, below. |
*p | T& | ||
*q | const T& | *q refers to the same object as *p | |
p->m | type of T::m | pre: (*p).m is well-defined. equivalent to (*p).m | |
q->m | type of T::m | pre: (*q).m is well-defined. equivalent to (*q).m | |
static_- cast<X::pointer>(w) | X::pointer | static_cast<X::pointer>(w) == p | |
static_cast<X ::const_pointer>(z) | X::const_pointer | static_cast<X ::const_pointer>(z) == q | |
a.allocate(n) | X::pointer | Memory is allocated for n objects of type T but objects are not constructed. allocate may raise an appropriate exception.181 [ Note: If n == 0, the return value is unspecified. — end note ] | |
a.allocate(n, u) | X::pointer | Same as a.allocate(n). The use of u is unspecified, but it is intended as an aid to locality. | a.allocate(n) |
a.deallocate(p,n) | (not used) | All n T objects in the area pointed to by p shall be destroyed prior to this call. n shall match the value passed to allocate to obtain this memory. Does not throw exceptions. [ Note: p shall not be singular. — end note ] | |
a.max_size() | X::size_type | the largest value that can meaningfully be passed to X::allocate() | numeric_limits<size_type>::max() |
a1 == a2 | bool | returns true only if storage allocated from each can be deallocated via the other. operator== shall be reflexive, symmetric, and transitive, and shall not exit via an exception. | |
a1 != a2 | bool | same as !(a1 == a2) | |
a == b | bool | same as a == Y::rebind<T>::other(b) | |
a != b | bool | same as !(a == b) | |
X a1(a); X a1 = a; |
Shall not exit via an exception. post: a1 == a | ||
X a(b); |
Shall not exit via an exception. post: Y(a) == b, a == X(b) | ||
X a1(move(a)); X a1 = move(a); |
Shall not exit via an exception. post: a1 equals the prior value of a. | ||
X a(move(b)); |
Shall not exit via an exception. post: a equals the prior value of X(b). | ||
a.construct(c, args) | (not used) | Effect: Constructs an object of type C at c | ::new ((void*)c) C(forward<Args>(args)...) |
a.destroy(c) | (not used) | Effect: Destroys the object at c | c->~C() |
a.select_on_container_copy_construction() | X | Typically returns either a or X() | return a; |
X::propagate_on_container_copy_assignment | Identical to or derived from true_type or false_type | true_type only if an allocator of type X should be copied when the client container is copy-assigned. | false_type |
X::propagate_on_container_move_assignment | Identical to or derived from true_type or false_type | true_type only if an allocator of type X should be moved when the client container is move-assigned. | false_type |
X::propagate_on_- container_swap | Identical to or derived from true_type or false_type | true_type only if an allocator of type X should be swapped when the client container is swapped. | false_type |
Note A: The member class template rebind in the table above is effectively a typedef template. [ Note: In general, if the name Allocator is bound to SomeAllocator<T>, then Allocator::rebind<U>::other is the same type as SomeAllocator<U>, where SomeAllocator<T>::value_type is T and SomeAllocator<U>::value_type is U. — end note ] If Allocator is a class template instantiation of the form SomeAllocator<T, Args>, where Args is zero or more type arguments, and Allocator does not supply a rebind member template, the standard allocator_traits template uses SomeAllocator<U, Args> in place of Allocator::rebind<U>::other by default. For allocator types that are not template instantiations of the above form, no default is provided.
An allocator type X shall satisfy the requirements of CopyConstructible ([utility.arg.requirements]). The X::pointer, X::const_pointer, X::void_pointer, and X::const_void_pointer types shall satisfy the requirements of NullablePointer ([nullablepointer.requirements]). No constructor, comparison operator, copy operation, move operation, or swap operation on these types shall exit via an exception. X::pointer and X::const_pointer shall also satisfy the requirements for a random access iterator ([iterator.requirements]).
Let x1 and x2 denote objects of (possibly different) types X::void_pointer, X::const_void_pointer, X::pointer, or X::const_pointer. Then, x1 and x2 are equivalently-valued pointer values, if and only if both x1 and x2 can be explicitly converted to the two corresponding objects px1 and px2 of type X::const_pointer, using a sequence of static_casts using only these four types, and the expression px1 == px2 evaluates to true.
Let w1 and w2 denote objects of type X::void_pointer. Then for the expressions
w1 == w2 w1 != w2
either or both objects may be replaced by an equivalently-valued object of type X::const_void_pointer with no change in semantics.
Let p1 and p2 denote objects of type X::pointer. Then for the expressions
p1 == 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 type X::const_pointer with no change in semantics.
An allocator may constrain the types on which it can be instantiated and the arguments for which its construct member may be called. If a type cannot be used with a particular allocator, the allocator class or the call to construct may fail to instantiate.
[ Example: the following is an allocator class template supporting the minimal interface that satisfies the requirements of Table [tab:utilities.allocator.requirements]:
template <class Tp> struct SimpleAllocator { typedef Tp value_type; SimpleAllocator(ctor args); template <class T> SimpleAllocator(const SimpleAllocator<T>& other); Tp* allocate(std::size_t n); void deallocate(Tp* p, std::size_t n); }; template <class T, class U> bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&); template <class T, class U> bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&);
— end example ]
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. The allocator also may silently ignore the requested alignment. [ Note: Additionally, the member function allocate for that type may fail by throwing an object of type std::bad_alloc. — end note ]
It is intended that a.allocate be an efficient means of allocating a single object of type T, even when sizeof(T) is small. That is, there is no need for a container to maintain its own free list.