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