Позволяет ли C++11 вектор?


требования к контейнерам изменились с C++03 на C++11. В то время как C++03 имел общие требования (например, конструктивность копирования и назначаемость для вектора), C++11 определяет мелкозернистые требования для каждой операции контейнера (раздел 23.2).

в результате вы можете, например, хранить тип, который является копируемым, но не назначаемым-например, структура с членом const - в векторе, пока вы выполняете только определенные операции, которые не требуют назначения (строительство и push_back такие операции; insert нет).

мне интересно: означает ли это, что стандарт теперь позволяет vector<const T>? Я не вижу причин, почему бы ему не...const T, как и структура с членом const, это тип, который можно копировать, но не назначать-но я, возможно, что-то пропустил.

(часть того, что заставляет меня думать, что я, возможно, что-то пропустил, это то, что GCC trunk падает и горит, если вы пытаетесь создать экземпляр vector<const T>, но это vector<T> где T имеет член const).

4 52

4 ответа:

Нет, я считаю, что требования распределителя говорят, что T может быть "неконстантным, не ссылочным типом объекта".

вы не смогли бы сделать много с вектором постоянных объектов. И const vector<T> было бы почти то же самое в любом случае.


много лет спустя этот быстрый и грязный ответ все еще, кажется, привлекает комментарии и голоса. Не всегда. : -)

Итак, чтобы добавить некоторые правильные ссылки:

для Стандарт C++03, который у меня есть на бумаге, таблица 31 в разделе [lib.распределитель.требования] говорит:

T, U any type

Не так любой тип на самом деле работал.

Итак, следующий стандарт, C++11, говорит в близком проекте в [распределителя.требования] а теперь таблица 27:

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

, который находится очень близко к тому, что я написал выше по памяти. Это тоже то, что вопрос был примерно такой.

однако, в C++14 (проект N4296) таблица 27 теперь говорит:

T, U, C any non-const object type

возможно, потому что ссылка, возможно, не является типом объекта в конце концов?

а теперь в C++17 (проект N4659) это таблица 30, которая говорит:

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

не только const исключено, но и volatile. Вероятно, старые новости в любом случае, и просто осветление.


см. Также информация из первых рук Говарда Хиннанта в настоящее время право ниже.

обновление

под принятым (и правильным) ответом я прокомментировал в 2011 году:

итог: мы не проектировали контейнеры для хранения const T. Хотя я подумай немного. И мы были очень близки с ней авария. Насколько мне известно, текущая точка преткновения-это пара перегружена address функции-члены по умолчанию распределитель: когда T и const эти две перегрузки же подпись. Простой способ исправить это было бы специализироваться std::allocator<const T> и удалите одну из перегрузок.

с предстоящим проектом C++17 мне кажется, что мы теперь легализованы vector<const T> и я также считаю, что мы сделали это случайно. : -)

P0174R0 снимает address перегрузки от std::allocator<T>. P0174R0 не упоминает о поддержке std::allocator<const T> в рамках своей обоснование.

коррекция

в комментариях ниже T. C. правильно отмечает, что address перегрузки устаревший, не удаляется. Моя ошибка. Устаревшие члены не отображаются в 20.10.9, где std::allocator определены, но вместо этого отнесены к разделу D. 9. Я забыл просмотреть главу D для этой возможности, когда я опубликовал это.

спасибо T. C. за исправление. Я подумывал об удалении этого заблуждения ответьте, но, возможно, лучше оставить его с этой поправкой, чтобы, возможно, это удержит кого-то другого от неправильного прочтения спецификации так же, как и я.

хотя у нас уже есть очень хорошие ответы на этот вопрос, я решил внести свой вклад с более практическим ответом, чтобы показать, что можно и что нельзя сделать.

так что это не работает:

vector<const T> vec; 

просто читать другие ответы, чтобы понять, почему. И, как вы уже догадались, это не работает:

vector<const shared_ptr<T>> vec;

T уже нет const, а vector держит shared_ptr, а не T s.

С другой стороны, это тут работы:

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

но в этом случае const-это объект, на который указывают, а не сам указатель (который хранится в векторе). Это было бы эквивалентно:

vector<shared_ptr<const T>> vec;

это нормально.

но если мы ставим const в конце выражения, теперь он превращает указатель в const, поэтому следующее не будет компилироваться:

vector<T * const> vec;

немного запутанно, я согласен, но вы привыкнете к этому.

дополняя другие ответы, другой подход заключается в использовании:

vector<unique_ptr<const T>> vec;

если это тот случай, когда вы хотите обеспечить что только vec имеет право собственности на его элементы. Или если вы хотите динамическое перемещение элементов в vec и в какой-то момент их вытащить.

как указано, указатель const семантика может быть запутанной, но shared_ptr и unique_ptr нет. const unique_ptr<T> является указателем const и unique_ptr<const T> является постоянным пунктом, как и следовало ожидать.