El contenedor reutiliza su asignador para asignar su propio material de contabilidad. (No es que importa para un std::list
, pero es cierto en general *.) Esta es la razón por los requisitos asignador estándar exigen la existencia de la plantilla rebind
:
typedef typename Alloc::template rebind<MyInternalStuff>::other internal_allocator;
Si el asignador es Alloc = my_allocator<T>
, entonces internal_allocator
convierte my_allocator<MyInternalStuff>
.
Creo que esta fue una de las quejas que Electronic Arts tuvo con la biblioteca estándar de C++, razón por la cual su biblioteca EASTL usa una convención diferente para asignadores que ofrece un control más estricto.
*) Normalmente, cada nodo será un objeto monolítico de algún tipo Node<T>
, así que supongo std::list<T, Alloc>
solamente nunca utiliza Alloc::rebind<Node<T>>::other
como asignador.
[Disculpa las múltiples ediciones; Tuve la salida destrozada y no la interpreté correctamente; Ahora fui e imprimí cada contenedor por separado y arreglé la salida en consecuencia. std::list
en efecto, sólo requieren una asignador]
Actualización:. Sólo por diversión, escribí un poco de desenredo-asignador que imprime su propio nombre de tipo en la construcción. Aquí está la entrada:
#include <unordered_map>
#include <set>
#include <deque>
#include <list>
#include <vector>
#include <map>
#include <iostream>
int main()
{
std::cout << "----- unordered_map<int, double> -----------" << std::endl;
std::unordered_map<int, double, std::hash<int>, std::equal_to<int>, funky_allocator<std::pair<const int, double>>> m { {1, 1.2} };
std::cout << "----- set<int> -----------------------------" << std::endl;
std::set<int, std::less<int>, funky_allocator<int>> s;
std::cout << "----- deque<int> ---------------------------" << std::endl;
std::deque<int, funky_allocator<int>> d;
std::cout << "----- list<int> ----------------------------" << std::endl;
std::list<int, funky_allocator<int>> l;
std::cout << "----- vector<int> --------------------------" << std::endl;
std::vector<int, funky_allocator<int>> c;
std::cout << "----- map<int, bool> -----------------------" << std::endl;
std::map<int, bool, std::less<int>, funky_allocator<std::pair<const int, bool>>> n { { 1, true } };
}
Y aquí el resultado:
----- unordered_map<int, double> -----------
Default-construct: funky_allocator<std::pair<int const, double> >
Copy-construct: funky_allocator<std::__detail::_Hash_node<std::pair<int const, double>, false> >
Copy-construct: funky_allocator<std::__detail::_Hash_node<std::pair<int const, double>, false>*>
----- set<int> -----------------------------
Default-construct: funky_allocator<std::_Rb_tree_node<int> >
----- deque<int> ---------------------------
Default-construct: funky_allocator<int>
Copy-construct: funky_allocator<int*>
----- list<int> ----------------------------
Default-construct: funky_allocator<std::_List_node<int> >
----- vector<int> --------------------------
Default-construct: funky_allocator<int>
----- map<int, bool> -----------------------
Default-construct: funky_allocator<std::_Rb_tree_node<std::pair<int const, bool> > >
Los detalles varían en función de la cual se utiliza el constructor: Contenedores como set
y map
sólo se podría construir el asignador "correcta" de alguna invocación, mientras que en otro pueden construir un objeto del asignador especificado primero. De cualquier manera, el asignador especificado nunca se usa en absoluto para un par de contenedores, y solo se utiliza la versión de rebote.
¿Te refieres a la implementación de la Biblioteca estándar de STL o C++ que se envía con tu cadena de herramientas elegida? ¿Y cuál es ese? –
@ TomalakGeret'kal, ¿qué? (+1 a la pregunta) – avakar
@avakar El STL fue originalmente un proyecto sgi. Desde entonces ha habido varias implementaciones de STL (como STLport) y gran parte de ella se ha agregado a la biblioteca estándar según lo define el comité, aunque con algunos cambios. Todo lo cual deja * * STL * * un poquito ambiguo en formas que pueden afectar esta pregunta. – dmckee