C ++ 11 consente il vettore ?

I requisiti del contenitore sono cambiati da C ++ 03 a C ++ 11. Mentre C ++ 03 aveva requisiti generali (ad es. Copiabilità e assegnabilità per il vettore), C ++ 11 definisce i requisiti a grana fine su ciascuna operazione del contenitore (sezione 23.2).

Di conseguenza, è ansible ad esempio memorizzare un tipo che è costruibile con la copia ma non assegnabile – come una struttura con un membro const – in un vettore se si eseguono solo determinate operazioni che non richiedono l’assegnazione (costruzione e push_back sono tali operazioni, insert non è).

Quello che mi chiedo è: questo significa che lo standard ora consente il vector ? Non vedo alcuna ragione che non dovrebbe – const T , proprio come una struttura con un membro const, è un tipo che è una copia costruibile ma non assegnabile – ma potrei aver perso qualcosa.

(Parte di ciò che mi fa pensare che mi sia sfuggito qualcosa, è che il tronco di gcc si blocca e brucia se si tenta di istanziare il vector , ma va bene con il vector dove T ha un membro const).

No, credo che i requisiti degli allocatori dicano che T può essere un “tipo di object non di riferimento, non di riferimento”.

Non saresti in grado di fare molto con un vettore di oggetti costanti. E un const vector sarebbe quasi lo stesso comunque.


Molti anni dopo questa risposta veloce e sporca sembra ancora attrarre commenti e voti. Non sempre attivo 🙂

Quindi per aggiungere alcuni riferimenti appropriati:

Per lo standard C ++ 03, che ho sulla carta, la Tabella 31 nella sezione [lib.allocator.requirements] dice:

T, U any type

Non che qualsiasi tipo funzionasse davvero.

Quindi, lo standard successivo, C ++ 11, dice in una bozza stretta in [allocator.requirements] e ora Tabella 27:

T, U, C any non-const, non-reference object type

che è estremamente vicino a quello che ho scritto in precedenza dalla memoria. Questo è anche di cosa si trattava.

Tuttavia, in C ++ 14 ( bozza N4296 ), la Tabella 27 ora dice:

T, U, C any non-const object type

Forse perché un riferimento forse non è un tipo di object, dopo tutto?

E ora in C ++ 17 ( bozza N4659 ) è la Tabella 30 che dice:

T, U, C any cv-unqualified object type (6.9)

Quindi non solo è escluso, ma anche volatile . Probabilmente vecchie notizie comunque, e solo un chiarimento.


Si prega di consultare anche le informazioni di prima mano di Howard Hinnant , attualmente sotto.

Aggiornare

Sotto la risposta accettata (e corretta) che ho commentato nel 2011:

In conclusione: non abbiamo progettato contenitori per contenere const T Anche se ci ho pensato un po ‘. E siamo arrivati ​​davvero vicini a farlo per caso. Per quanto ne so, l’attuale punto critico è la coppia di funzioni membro di address sovraccarico nell’assegnatore predefinito: quando T è const , questi due overload hanno la stessa firma. Un modo semplice per correggere ciò sarebbe specializzare std::allocator e rimuovere uno degli overload.

Con l’imminente bozza di C ++ 17 mi sembra che ora abbiamo legalizzato il vector , e credo anche che lo abbiamo fatto accidentalmente . 🙂

P0174R0 rimuove gli overload di address da std::allocator . P0174R0 non menziona il supporto di std::allocator come parte della sua logica.

Correzione

Nei commenti che seguono TC rileva correttamente che gli overload degli address sono deprecati , non rimossi. Colpa mia. I membri deprecati non vengono visualizzati in 20.10.9 dove è definito lo std::allocator , ma sono invece relegati alla sezione D.9. Ho trascurato di analizzare il capitolo D per questa possibilità quando l’ho postato.

Grazie TC per la correzione. Ho pensato di cancellare questa risposta fuorviante, ma forse è meglio lasciar perdere questa correzione in modo che forse impedirà a qualcun altro di interpretare erroneamente le specifiche nello stesso modo in cui l’ho fatto io.

Anche se abbiamo già ottime risposte su questo, ho deciso di contribuire con una risposta più pratica per mostrare cosa può e cosa non può essere fatto.

Quindi questo non funziona:

 vector vec; 

Basta leggere le altre risposte per capire perché. E, come avrai intuito, anche questo non funzionerà:

 vector> vec; 

T non è più const , ma vector sta tenendo shared_ptr s, non T s.

D’altra parte, questo funziona:

 vector vec; vector vec; // the same as above 

Ma in questo caso, const è l’object puntato, non il puntatore stesso (che è ciò che il vettore memorizza). Questo sarebbe equivalente a:

 vector> vec; 

Che va bene

Ma se mettiamo const alla fine dell’espressione, ora trasforma il puntatore in un const , quindi il seguente non verrà compilato:

 vector vec; 

Un po ‘di confusione, sono d’accordo, ma ti ci abitui.

A complemento delle altre risposte, un altro approccio è quello di utilizzare:

 vector> vec; 

Se è il caso in cui si desidera applicare che solo vec ha la proprietà dei suoi articoli. O se vuoi una dynamic di spostare gli oggetti in vec e ad un certo punto spostarli.

Come sottolineato, la semantica di pointer const potrebbe confondere, ma shared_ptr e unique_ptr non lo sono. const unique_ptr è un puntatore const e unique_ptr è una punta costante come ci si aspetterebbe.