VС++ позволяет использовать типы const для контейнеров STL. Зачем?

Контейнеры STL требуют, чтобы сохраненные значения копировались конструктивно и присваивались. const T, очевидно, не является назначаемым типом для любого T, но я пытался его использовать (просто любопытно) и выяснил, что он компилируется и, более того, ведет себя как назначаемый тип.

vector<const int> v(1);
v[0] = 17;

Это успешно выполняется в Visual Studio 2008 и назначает v [0] - 17.

Ответ 1

Это не ошибка в реализации, как предложили другие.

Нарушение требований стандартной библиотеки С++ не делает вашу программу плохо сформированной, она дает поведение undefined.

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

Соответствующий язык из стандарта С++ можно найти в С++ 03 17.4.3.6 [lib.res.on.functions]:

В некоторых случаях (функции замены, функции обработчика, операции с типами, используемыми для создания стандартных компонентов шаблона библиотеки) стандартная библиотека С++ зависит от компонентов, поставляемых программой на С++. Если эти компоненты не соответствуют их требованиям, Стандарт не устанавливает никаких требований к реализации.

В частности, эффекты undefined в следующих случаях:

...

  • для типов, используемых в качестве аргументов шаблона при создании экземпляра компонента шаблона, если операции с типом не реализуют семантику применимого подраздела Требования.

Реализация Visual С++ Standard Library может делать что-либо с этим кодом, включая тихое удаление или игнорирование const-qualification, и оно по-прежнему соответствует стандартам.

Ответ 2

<ы > Это просто не должно работать. В §23.1 ¶ 3 он, как вы сказали, указал, что объекты, хранящиеся в контейнере, должны быть CopyConstructible (как указано в §20.1.3) и Assignable.

Требования Assignable для типа T заключаются в том, что T и u для типа T можно сделать:

t = u

с T& в качестве возвращаемого значения и T эквивалентно u в качестве постусловия. (§23.1 ¶4)

Таким образом, типы const явно не Assignable, так как при выполнении t = u возникает ошибка компиляции (§7.1.5.1 ¶5).

Я полагаю, что это ошибка в реализации Microsoft. g++ в Linux испускает типичную ошибку шаблона 25 килограммов, если вы даже пытаетесь создать экземпляр vector<const int> (протестирован как с флагом -std=c++0x, так и без него).

Кстати, это также подробно объясняется в этом Часто задаваемые вопросы IBM.


В теории, как сказал @James McNellis, компилятор не должен взорвать векторную инстанцировку (если это поведение undefined может произойти, в том числе все работает нормально); однако в инструкции присваивания есть нарушение стандарта, который должен приводить к ошибке компиляции.

В фактах член operator[] возвращает a vector<const int>::reference; что требуется быть значением l T (§23.1 ¶5 таблица 66); поскольку T имеет тип const, это будет const lvalue. Таким образом, мы падаем до (§7.1.5.1 ¶5), который определяет код, который пытается выполнить присвоение элементу const как "плохо сформированный", и это требует ошибки компиляции или, по крайней мере, предупреждения, поскольку присвоение -to- const является диагностическим правилом (§1.4 ¶1-2) (нет инструкции "без диагностики" ). С >


Окончательное редактирование

Собственно, @James McNellis прав; после того, как вы вызвали поведение undefined путем создания экземпляра vector<const int>, обычные правила перестают иметь значение, поэтому реализация по-прежнему соответствует стандарту, независимо от того, что он делает - включая удаление const из типа элемента или создание обычных носовых демонов.