2013-01-03 17 views
10

cercando di imparare di più su come la libreria standard è effettivamente implementata sto ispezionando tutti i contenitori in Visual Studio .. Qui vedo un po 'curiosa struttura:cosa fa (template) rebind <> do?

In alcuni classe base di un std::list<> Il seguente typedef si trova

typedef typename _Alloc::template rebind<_Ty>::other _Alty; 

Dove "_Alloc" corrisponde all'argomento del template di allocatore (e _Ty il tipo contenuto). Ho difficoltà a trovare una buona spiegazione di questa "parola chiave". La cosa migliore che ho trovato finora è che fa parte dell'interfaccia di allocatore. Sebbene anche lo cppreference non sia molto buono nello spiegare questo.

Cosa fa questo template rebind<>? E perché è necessario in quella posizione?

+0

Correlato, vedere [Perché è necessario allocatore: eseguire nuovamente il rebind quando sono disponibili i parametri modello modello?] (Http://stackoverflow.com/q/12362363) – jww

risposta

14

il modello _Alloc viene utilizzato per ottenere oggetti di un certo tipo. Il contenitore potrebbe avere una necessità interna di allocare oggetti di un tipo diverso. Ad esempio, se si dispone di std::list<T, A>, l'allocatore A è destinato ad allocare oggetti di tipo T ma lo std::list<T, A> in realtà deve allocare oggetti di tipo di nodo. Chiamando il tipo di nodo _Ty, lo std::list<T, A> deve ottenere un allocatore per gli oggetti _Ty che utilizza il meccanismo di allocazione fornito da A. Utilizzo di

typename _A::template rebind<_Ty>::other 

specifica il tipo corrispondente. Ora, ci sono alcuni fastidi sintattiche in questa dichiarazione:

  1. Dal rebind è un modello di membro del _A e _A è un argomento di un template, il rebind diventa un nome dipendente. Per indicare che un nome dipendente è un modello, deve essere preceduto da template. Senza la parola chiave template, l'operatore < sarebbe considerato l'operatore minore di.
  2. Il nome other dipende anche da un argomento modello, vale a dire, è anche un nome dipendente. Per indicare che un nome dipendente è un tipo, è necessaria la parola chiave typename.
+0

Attendi, ma ciò significherebbe che (quando l'elenco è 'std :: lista '); 'rebind ' diventa ridondante? come convertirebbe "T" in "T"? – paul23

+0

@ paul23: Se '_Ty' è l'argomento del modello, piuttosto che qualcosa come' typedef _Node <_T> _Ty', potrebbe essere utile assicurarsi che l'allocatore crei i tipi appropriati. Anche se sono abbastanza sicuro che 'A' in' std :: list 'deve essere in grado di gestire gli oggetti' T', può essere passato un allocatore di un diverso. Non sono sicuro dei requisiti standard. Potrebbe essere un'estensione per supportare gli allocatori per diversi tipi. –

+0

L'elenco di T alloca i nodi che contengono T come membro. Quindi l'allocatore T è inutile direttamente. Invece ne crea uno nuovo. Il tuo commento non ha senso per me @ paul23 – Yakk

3

rebind è per l'allocazione di memoria per un tipo che differisce dal tipo di elemento del contenitore in corso di implementazione. Prendere da this MSDN article:

Per esempio, dato un al oggetto allocatore di tipo A, è possibile allocare un oggetto di tipo _Altri con l'espressione:

A::rebind<Other>::other(al).allocate(1, (Other *)0)

In alternativa, è possibile assegnare un nome il suo tipo di puntatore da scrittura del tipo:

A::rebind<Other>::other::pointer

0

prega di consultare questo http://www.cplusplus.com/reference/memory/allocator/

vedrete

REBIND < ...> è in realtà un membro della classe di allocatore che fa parte del STL senza dare il codice sorgente dell'applicazione.

come si vede, rebind < ...> è anche un modello e merita un tipo per consentire alla classe allocatore di sapere cosa c'è nel mio membro di rebind.

quindi indietro alla vostra dichiarazione: typedef typename _Alloc :: template rebind < _Ty> :: other _Alty; se si omette il modello: typedef typename _Alloc :: rebind < _Ty> :: other _Alty; puoi facilmente capire che rebind è membro di _Alloc, ma il compilatore NON può capire.

Data la natura del modello di rebinding, il modello rebind < _Ty> è necessario ed è considerato come il tutto non due parti.

0

Esempio nel codice di STDC++: /usr/include/4.8/ext/new_allocator.h

rebind è definito come un membro della struttura della classe allocatore; questa struttura definisce un membro altra definito come un'istanza allocatore specializzata per un diverso tipo di argomento (l'altro membro definisce una classe allocatore che può crea un tipo diverso di oggetti)

template<typename _Tp> 
    class new_allocator 
    { 
    public: 
     ... 
     template<typename _Tp1> 
     struct rebind 
     { typedef new_allocator<_Tp1> other; }; 

Quando viene utilizzato:

typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type; 

il tipo di allocatore viene fatto riferimento come

typename _Alloc::template rebind<_Tp>::other 

Ora il typedef viene utilizzato per definire _Tp_alloc_type - che può quindi essere utilizzato come nome più breve per la stessa cosa.

Un esempio di utilizzo è in std :: list in cui anche il nodo elenco interno necessita del relativo allocatore, che viene ridefinito dall'argomento allocatore.