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
из типа элемента или создание обычных носовых демонов.