Il contenitore rielabora effettivamente l'allocatore per allocare il proprio materiale di conservazione dei libri. (Non che sarebbe importa per un std::list
, ma è vero in generale *). Questo è il motivo per cui i requisiti allocatore standard, impongono l'esistenza del modello rebind
:
typedef typename Alloc::template rebind<MyInternalStuff>::other internal_allocator;
Se il vostro allocatore è Alloc = my_allocator<T>
, quindi internal_allocator
diventa my_allocator<MyInternalStuff>
.
Credo che questo fosse uno dei problemi che Electronic Arts aveva con la libreria standard C++, motivo per cui la loro libreria EASTL utilizza una convenzione diversa per gli allocatori che offre un controllo più stretto.
*) Tipicamente, ogni nodo sarà un oggetto monolitico di qualche tipo Node<T>
, quindi suppongo std::list<T, Alloc>
solo mai utilizza Alloc::rebind<Node<T>>::other
come allocatore.
[Mi dispiace per le modifiche multiple; Ho avuto l'output maciullato e non l'ho interpretato correttamente; Ora andavo a stampare ogni contenitore separatamente e aggiustavo l'output di conseguenza. std::list
effettivamente richiede solo una allocatore]
Aggiornamento:. Solo per risatine, ho scritto un po 'di decodifica-allocator che stampa il proprio typename su di costruzione. Ecco l'ingresso:
#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 } };
}
E qui l'output:
----- 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> > >
I dettagli variano a seconda di quale viene utilizzato costruttore: contenitori come set
e map
potrebbe costruire solo l'allocatore "corretta" in qualche invocazione, mentre in un altro possono costruire prima un oggetto dell'allocatore specificato. In entrambi i casi, l'allocatore specificato non viene mai utilizzato affatto per un paio di contenitori e solo viene utilizzata la versione di ritorno.
Si intende l'implementazione della libreria standard STL o C++ fornita con la toolchain scelta? E quale è quello? –
@ TomalakGeret'kal, cosa? (+1 alla domanda) – avakar
@avakar L'STL era originariamente un progetto SGI. Da allora ci sono state diverse implementazioni del STL (come STLport) e gran parte di esso è stato aggiunto alla libreria standard come definito dal comitato, anche se con alcune modifiche. Tutto ciò lascia * "STL" * un po 'ambiguo in modi che potrebbero influenzare questa domanda. – dmckee