[allocator.requirements] (original) (raw)

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.

Table 35: Descriptive variable definitions [tab:allocator.req.var]

Variable Definition
T, U, C any cv-unqualified object type ([basic.types])
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>
a, a1, a2 lvalues of type X
u the name of a variable being declared
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_­pointerobtained by conversion from a value p
r a value of type T&obtained by the expression *p
w a value of type XX​::​void_­pointer obtained by conversion from a value p
x a value of type XX​::​const_­void_­pointer obtained by conversion from a value q or a value w
y 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
n a value of type XX​::​size_­type
Args a template parameter pack
args a function parameter pack with the pattern Args&&

The class template allocator_­traits ([allocator.traits]) supplies a uniform interface to all allocator types.

Table 35 describes the types manipulated through allocators.

Table 36describes the requirements on allocator types and thus on types used to instantiate allocator_­traits.

A requirement is optional if the last column of Table 36 specifies a default for a given expression.

Within the standard library allocator_­traitstemplate, an optional requirement that is not supplied by an allocator is replaced by the specified default expression.

A user specialization ofallocator_­traits may provide different defaults and may provide defaults for different requirements than the primary template.

Within Tables 35 and 36, the use of move and forward always refers to std​::​moveand std​::​forward, respectively.

Table 36: Cpp17Allocator requirements [tab:cpp17.allocator]

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_­pointerY​::​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_­pointerY​::​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 Preconditions: (*p).m is well-defined. equivalent to (*p).m
q->m type of T​::​m Preconditions: (*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​>(x) X​::​const_­pointer static_­cast< X​::​const_­pointer​>(x) == q
pointer_­traits<​X​::​pointer​>​::​pointer_­to(r) X​::​pointer same as p
a.allocate(n) X​::​pointer Memory is allocated for an array of n Tand such an object is created but array elements are not constructed. [ Example: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.end example ] allocate may throw an appropriate exception.171 [ Note:If n == 0, the return value is unspecified.end note ]
a.allocate(n, y) X​::​pointer Same as a.allocate(n). The use of y is unspecified, but it is intended as an aid to locality. a.allocate(n)
a.deallocate(p,n) (not used) Preconditions: p is a value returned by an earlier call to allocate that has not been invalidated by an intervening call to deallocate. n matches the value passed to allocate to obtain this memory. Throws: Nothing.
a.max_­size() X​::​size_­type the largest value that can meaningfully be passed to X​::​allocate() numeric_­limits<size_­type>​::​max() / sizeof​(value_­type)
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 u(a); X u = a; Shall not exit via an exception. Postconditions: u == a
X u(b); Shall not exit via an exception. Postconditions: Y(u) == b, u == X(b)
X u(std​::​move(a)); X u = std​::​move(a); Shall not exit via an exception. Postconditions: The value of a is unchanged and is equal to u.
X u(std​::​move(b)); Shall not exit via an exception. Postconditions: u is equal to the prior value of X(b).
a.construct(c, args) (not used) Effects: Constructs an object of type C atc. construct_­at(c, std​::​​forward<Args>​(args)...)
a.destroy(c) (not used) Effects: Destroys the object at c destroy_­at(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. See Note B, below. 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. See Note B, below. 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. See Note B, below. false_­type
X​::​is_­always_­equal Identical to or derived from true_­type or false_­type true_­type only if the expression a1 == a2 is guaranteed to be true for any two (possibly const) valuesa1, a2 of type X. is_­empty<X>​::​​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>, thenAllocator​::​rebind<U>​::​other is the same type asSomeAllocator<U>, whereSomeAllocator<T>​::​value_­type is T andSomeAllocator<U>​::​​value_­type is U.

end note

]

IfAllocator 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>​::​otherby default.

For allocator types that are not template instantiations of the above form, no default is provided.

Note B: If X​::​propagate_­on_­container_­copy_­assignment​::​value is true,X shall meet theCpp17CopyAssignable requirements (Table 31) and the copy operation shall not throw exceptions.

If X​::​propagate_­on_­container_­move_­assignment​::​value is true,X shall meet theCpp17MoveAssignable requirements (Table 30) and the move operation shall not throw exceptions.

If X​::​propagate_­on_­container_­swap​::​value is true, lvalues of type X shall be swappableand the swap operation shall not throw exceptions.

An allocator type X shall meet theCpp17CopyConstructible requirements (Table 29).

The X​::​pointer, X​::​const_­pointer, X​::​void_­pointer, andX​::​const_­void_­pointer types shall meet theCpp17NullablePointer requirements (Table 33).

No constructor, comparison function, copy operation, move operation, or swap operation on these pointer types shall exit via an exception.

X​::​pointer and X​::​const_­pointer shall also meet the requirements for a Cpp17RandomAccessIterator ([random.access.iterators]) and the additional requirement that, when a and (a + n) are dereferenceable pointer values for some integral value n,

addressof(*(a + n)) == addressof(*a) + n

is true.

Let x1 and x2 denote objects of (possibly different) typesX​::​void_­pointer, X​::​const_­void_­pointer, X​::​pointer, or X​::​const_­pointer.

Then, x1 and x2 areequivalently-valued pointer values, if and only if both x1 and x2can be explicitly converted to the two corresponding objects px1 and px2of type X​::​const_­pointer, using a sequence of static_­casts using only these four types, and the expression px1 == px2evaluates 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 typeX​::​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 typeX​::​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 or destroy members may be called.

If a type cannot be used with a particular allocator, the allocator class or the call to construct or destroy may fail to instantiate.

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 allocatefor that type may fail by throwing an object of typebad_­alloc.

end note

]

[ Example

:

The following is an allocator class template supporting the minimal interface that meets the requirements of Table 36:

template struct SimpleAllocator { typedef Tp value_type; SimpleAllocator(ctor args);

template SimpleAllocator(const SimpleAllocator& other);

[[nodiscard]] Tp* allocate(std::size_t n); void deallocate(Tp* p, std::size_t n); };

template<class T, class U> bool operator==(const SimpleAllocator&, const SimpleAllocator&); template<class T, class U> bool operator!=(const SimpleAllocator&, const SimpleAllocator&);

end example

]