Czy C++11 pozwala na wektor?

Wymagania kontenera uległy zmianie Z C++03 na C++11. Podczas gdy C++03 miał ogólne wymagania (np. kopiowalność i przypisywalność dla wektora), C++11 definiuje drobnoziarniste wymagania dotyczące każdej operacji kontenera (sekcja 23.2).

W rezultacie można np. zapisać typ, który jest kopiowalny, ale nie można go przypisać - np. struktura z elementem const - w wektorze, o ile wykonuje się tylko pewne operacje, które nie wymagają przypisania (Budowa i push_back są takie operacje; insert nie jest).

Zastanawiam się, czy to oznacza, że standard pozwala teraz vector<const T>? Nie widzę powodu, dla którego nie powinna - const T, podobnie jak struktura z członem const, jest typem, który można skopiować, ale nie można go przypisać - ale mogłem coś przeoczyć.

(część tego, co sprawia, że myślę, że mogłem coś przeoczyć, jest to, że bagażnik gcc ulega awarii i pali się, jeśli spróbujesz utworzyć instancję vector<const T>, ale jest w porządku z vector<T> Gdzie t ma członka const).

Author: HighCommander4, 2011-08-05

4 answers

Nie, wierzę, że wymagania alokatora mówią, że T może być "non-const, non-reference object type".

Nie byłabyś w stanie wiele zrobić z wektorem stałych obiektów. A const vector<T> i tak byłoby prawie takie samo.


wiele lat później ta szybka i brudna odpowiedź nadal wydaje się przyciągać komentarze i głosy. Nie zawsze w górę. :-)

aby dodać odpowiednie referencje:

Dla standardu C++03, który mam na papierze, tabela 31 w sekcji [lib.allocator.wymagania] says:

T, U any type

Nie to jakikolwiek typ faktycznie zadziałał.

Następny standard, C++11, mówi w bliskim szkicu w [allocator.wymagania] i teraz tabela 27:

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

Co jest niezwykle bliskie temu, co pierwotnie napisałem powyżej z pamięci. O to też chodziło w pytaniu.

Jednak w C++14 (draft N4296 ) Tabela 27 teraz says:

T, U, C any non-const object type

Być może dlatego, że Referencja może nie jest typem obiektu?

A teraz w C++17 (draft N4659 ) jest tabela 30, która mówi:

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

Więc nie tylko const jest wykluczone, ale także volatile. Pewnie i tak stare wiadomości i tylko Wyjaśnienie.


proszę również zobaczyć Howard Hinnant informacje z pierwszej ręki , obecnie tuż poniżej.

 34
Author: Bo Persson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-02 20:51:43

Update

Pod zaakceptowaną (i poprawną) odpowiedzią skomentowałem w 2011 roku:

Podsumowując: nie zaprojektowaliśmy kontenerów do przechowywania const T. Chociaż tak przemyśl to. I byliśmy naprawdę blisko zrobienia tego przez wypadek. Z tego co wiem, obecny punkt jest para przeciążonych address funkcji Członkowskich w domyślnej alokator: gdy T jest const, te dwa przeciążenia mają takie same podpis. Łatwy sposób na poprawienie tego byłoby specjalizować się std::allocator<const T> i usunąć jedno z przeciążeń.

W nadchodzącym projekcie C++17 wydaje mi się, że zalegalizowaliśmy vector<const T>, i wierzę również, że zrobiliśmy to przypadkowo. :-)

P0174R0 usuwa przeciążenia address z std::allocator<T>. P0174R0 nie wspomina o poparciu std::allocator<const T> w ramach swojego uzasadnienia.

Korekta

W komentarzach poniżej T. C. poprawnie zauważa, że address przeciążenia są przestarzałe , nie są usuwane. Mój błąd. Członkowie nie pojawiają się w 20.10.9, gdzie std::allocator jest zdefiniowany, ale zamiast tego są relegowani do sekcji D. 9. Zaniedbałem skanować Rozdział D dla tej możliwości, kiedy to opublikowałem.

Dziękuję T. C. za korektę. Rozważałem usunięcie tej mylącej odpowiedzi, ale być może najlepiej zostawić to z tą poprawką, aby być może powstrzyma to kogoś innego od błędnego odczytania specyfikacji w taki sam sposób jak ja tak.

 20
Author: Howard Hinnant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-27 21:21:22

Mimo że mamy już bardzo dobre odpowiedzi na ten temat, postanowiłem przedstawić bardziej praktyczną odpowiedź, aby pokazać, co można, a czego nie można zrobić.

Więc to nie działa:

vector<const T> vec; 

Po prostu przeczytaj inne odpowiedzi, aby zrozumieć dlaczego. I, jak pewnie się domyślacie, to też nie zadziała:

vector<const shared_ptr<T>> vec;

T nie jest już const, ale vector trzyma shared_ptr s, nie T s.

Z drugiej strony to Działa :

vector<const T *> vec;
vector<T const *> vec;  // the same as above

Ale w tym przypadku, const to obiekt, na który jest wskazywany, a nie sam wskaźnik (który przechowuje wektor). Byłoby to równoważne:

vector<shared_ptr<const T>> vec;
Co jest w porządku.

Ale jeśli umieścimy const na końcu wyrażenia, to teraz zamieni wskaźnik w const, więc nie będzie kompilacji:

vector<T * const> vec;
Trochę zagmatwane, zgadzam się, ale można się do tego przyzwyczaić.
 3
Author: Lucio Paiva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-08 00:29:40

Uzupełniając Pozostałe odpowiedzi, należy zastosować inne podejście:

vector<unique_ptr<const T>> vec;

Jeśli jest to przypadek, w którym chcesz wyegzekwować, że tylko vec ma własność swoich przedmiotów. Lub jeśli chcesz dynamicznie przenosić elementy do vec i w pewnym momencie je przenieść.

Jak wspomniano, semantyka pointer const może być myląca, ale shared_ptr i unique_ptr nie są. const unique_ptr<T> jest wskaźnikiem const, a unique_ptr<const T> jest wskaźnikiem const, jak można się spodziewać.

 2
Author: Daniel Gouvêa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-05 12:14:44