2014-12-15 14 views
7

Il modello C++ 11 std::allocator_traits viene utilizzato per eseguire una query su Allocator per determinare se propagate_on_copy_assignment e propagate_on_move_assignment è true. Questi valori influenzano il modo in cui i tipi di contenitore devono implementare l'assegnazione di copia e spostamento. Se std::allocator_traits<Allocator>::propagate_on_move_assignment == true un operatore di assegnazione spostamento contenitore deve spostare assegnare il suo oggetto allocatore interno utilizzando l'allocatore contenuto nell'oggetto contenitore RHS.Perché propagate_on_XXX_assignment non si applica ai costruttori?

Presumibilmente, il punto di questo è che così possiamo implementare Allocator tipi che possono informare il contenitore client o meno di un'operazione di move o copy dovrebbe richiedere che copiamo qualsiasi stato interno dentro l'allocatore.

Quindi ... perché questi typedef solo si applicano all'assegnazione. Perché non abbiamo propagate_on_copy_construct e propagate_on_move_construct? Se un allocatore ha uno stato interno, l'oggetto contenitore client non dovrebbe esserne a conoscenza in modo che sappia se deve o meno copiare/spostare l'allocatore?

risposta

9

In un'assegnazione ha due scelte:

  1. Mantenete il vostro allocatore esistente.
  2. Copia/sposta dall'allocatore rhs.

I tratti propagate_on_assign controllano la scelta per gli operatori di assegnazione.

Per la costruzione, la scelta 1 (mantenendo l'allocatore esistente) non è un'opzione. Lì non è un assegnatore esistente. Invece le tue scelte sono:

  1. Costruire un allocatore dal nulla.
  2. Copia/sposta dall'allocatore rhs.
  3. Copia/sposta da un'altra fonte.

La scelta può essere considerata: il predefinito costruisce un allocatore. La scelta 3 è piuttosto vaga, ma i diversi schemi di allocazione possono essere imprevedibili ed è bene dare al progettista di allocatori la massima flessibilità possibile: è possibile fare alcune cose che il comitato non ha mai previsto.

Nel tentativo di soddisfare tutte e tre le scelte, almeno per il costruttore contenitore copia, una nuova allocator_traits "switch" è stato progettato:

Alloc select_on_container_copy_construction(const Alloc& rhs); 

allocator_traits tornerà rhs. select_on_container_copy_construction() se questa espressione è ben formato. Altrimenti restituirà rhs. E i costruttori di copia contenitore sono necessari per utilizzare allocator_traits<A>:: select_on_container_copy_construction(a) durante la costruzione dell'allocazione lhs durante la costruzione della copia.

Per i progettatori di allocatori che desiderano solo che il loro allocatore copi durante la costruzione della copia (scelta 2), non devono fare nulla.

Allocator progettisti che vogliono avere il default LHS allocatore costruito sulla copia costruzione contenitore solo bisogno di scrivere la seguente funzione di membro per la loro allocatore:

Alloc select_on_container_copy_construction() const {return Alloc{};} 

E se pensano a qualcosa di intelligente per la scelta 3, che può probabilmente implementarlo usando lo stesso gancio della scelta 1.

Quindi per la copia non è necessario un tratto propagate_on poiché lo select_on_container_copy_construction copre già tutte le basi.

Per la costruzione mossa, vedere la parte inferiore della pagina 12 del N2982:

Si noti che non v'è alcuna select_on_container_move_construction() funzione. Dopo alcune considerazioni, abbiamo deciso che un'operazione di costruzione mossa dei contenitori deve eseguito in tempo costante e non gettare, come per numero 1166.

Infatti questo lavoro, e le carte che lo precede (a cui fa riferimento) sono una buona fonte di informazioni per la logica alla base del progetto di allocatore C++ 11. Questo documento fa riferimento anche a allocator_propagate_on_copy_construction da un precedente articolo, che successivamente si è evoluto in select_on_container_copy_construction().

+0

Grazie Jonathan! –

Problemi correlati