Requisitos denominados de C++: AllocatorAwareContainer (desde C++11)
Un contenedor que es consciente de asignador, AllocatorAwareContainer, es un contenedor, Container, que alberga una instancia de un asignador, Allocator, y usa esa instancia en todas sus funciones miembro para asignar y desasignar memoria y para construir y destruir objetos en esa memoria (tales objetos pueden ser elementos del contenedor, nodos, o para contenedores no ordenados, arrays de contenedores), excepto que las especializaciones std::basic_string no usan los asignadores para la construcción/destrucción de sus elementos (desde C++23).
Las siguientes reglas se aplican durante la construcción del contenedor:
- Los constructores de copia de los contenedores AllocatorAwareContainer obtienen sus instancias del asignador llamando a
std::allocator_traits<allocator_type>::select_on_container_copy_constructionen el asignador del contenedor que se está copiando. - Los constructores de movimiento obtienen sus instancias de los asignadores mediante la construccción por movimiento a partir del asignador que pertenece al contenedor viejo.
- Todos los demás constructores toman un parámetro
const allocator_type&.
La única manera de reemplazar un asignador es mediante la asignación de copia, asignación de movimiento e intercambio:
- La asignación de copia reemplazará al asignador solamente si
std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::valueestrue - La asignación de movimiento reemplazará al asignador solamente si
std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::valueestrue - El intercambio reemplazará al asignador solamente si
std::allocator_traits<allocator_type>::propagate_on_container_swap::valueestrue. Específicamente, intercambiará las instancias de asignador a través de una llamada no calificada a la función no miembroswap. Véase Swappable.
Nota: El comportamiento de intercambiar dos contenedores con asignadores desiguales si propagate_on_container_swap es false es indefinido.
- El descriptor de acceso
get_allocator()obtiene una copia del asignador que se usó para construir el contenedor o que se instaló en la operación de reemplazo de asignador más reciente.
Sumario
Requisitos
Un tipo satisface AllocatorAwareContainer si satisface Container, y, dados los siguientes tipos y valores, se satisfacen los requisitos de semántica y complejidad de las siguientes tablas:
| Tipo | Definición |
X
|
un tipo AllocatorAwareContainer |
T
|
el tipo de valor de X
|
A
|
el tipo de asignador usado por X
|
| Valor | Definición |
a, b
|
lvalores no constantes de tipo X
|
c
|
un lvalor de tipo const X
|
t
|
un lvalor o un rvalor constante de tipo X
|
rv
|
un rvalor no constante de tipo X
|
m
|
un valor de tipo A
|
Tipos
| Nombre | Tipo | Requisito |
|---|---|---|
typename X::allocator_type
|
A
|
X::allocator_type::value_type y X::value_type son lo mismo.
|
Sentencias
| Sentencia | Semántica | Complejidad | |
|---|---|---|---|
X u;X u = X();
|
Precondición | A es DefaultConstructible.
|
Constante |
| Poscondición | u.empty() y u.get_allocator() == A() son true.
| ||
X u(m);
|
Poscondición | u.empty() y u.get_allocator() == m son true.
|
Constante |
X u(t, m);
|
Precondición | T es CopyInsertable en X.
|
Lineal |
| Poscondición | u == t y u.get_allocator() == m son true.
| ||
X u(rv);
|
Poscondición |
|
Constante |
X u(rv, m);
|
Precondición | T es MoveInsertable en X.
|
|
| Poscondición |
|
Expresiones
| Expresión | Tipo | Semántica | Complejidad | |
|---|---|---|---|---|
c.get_allocator()
|
A
|
No hay requisito semántico directo. | Constante | |
a = t
|
X&
|
Precondición | T es CopyInsertable en X y CopyAssignable.
|
Lineal |
| Poscondición | a == t es true.
| |||
a = rv
|
X&
|
Precondición | Si el asignador no se reemplazará por asignación de movimiento (véase más arriba), entonces T es MoveInsertable en X y MoveAssignable.
|
Lineal |
| Efecto | Todos los elementos existentes de a se asignan por movimiento o se destruyen.
| |||
| Poscondición | Si a y rv no se refieren al mismo objeto, a es igual al valor que rv tenían antes de la asignación.
| |||
a.swap(b)
|
void
|
Efecto | Intercambia el contenido de a y b.
|
Constante |
Notas
Los contenedores conscientes de asignador siempre llamarán a std::allocator_traits<A>::construct(m, p, args) para construir un objeto de tipo T en p usando args, con m == get_allocator(). La construcción predeterminada en std::allocator llama a ::new((void*)p) T(args) (hasta C++20)std::allocator no tiene miembro de construcción y se llama a std::construct_at(p, args) cuando se crean elementos (desde C++20), pero asigandores especializados pueden escoger una definición distinta.
Biblioteca estándar
Todos los tipos cadena de caracteres y contenedores (excepto std::array y std::inplace_vector) de la biblioteca estándar son AllocatorAwareContainer:
- std::basic_string
- std::deque
- std::forward_list
- std::list
- std::vector
- std::map
- std::multimap
- std::set
- std::multiset
- std::unordered_map
- std::unordered_multimap
- std::unordered_set
- std::unordered_multiset
Defect reports
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
| ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2839 | C++11 | No se permitía la auto asignación de movimiento de contenedores estándar | permitido pero el resultado no está especificado |