Позволяет ли 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 ответа:
Нет, я считаю, что требования распределителя говорят, что 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>
является постоянным пунктом, как и следовало ожидать.