Это просто не должно работать. В §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>
(на всякий случай протестировано как с флагом * 1025, так и без него).
Кстати, это также подробно объясняется в этом IBM FAQ .
<ч />
Теоретически, как сказал @James McNellis, компилятору не требуется взрывать создание экземпляров вектора (если это неопределенное поведение, может произойти все что угодно - включая все, что работает нормально); однако в операторе присваивания есть нарушение стандарта, которое должно привести к ошибке компиляции.
Фактически, член operator[]
возвращает vector<const int>::reference
; что каждый должен быть lvalue T
(§23.1-5 таблица 66); поскольку T
имеет тип const
, это будет const
lvalue. Таким образом, мы переходим к (§7.1.5.1 )5), который определяет код, который пытается выполнить присваивание элементу const
, как «плохо сформированный», и это требует ошибки компиляции или, по крайней мере, предупреждения, потому что присваивание -to- const
- это диагностируемое правило (§1.4 ¶1-2) (оператор «диагностика не требуется» не указан).
<ч />
Окончательное редактирование
На самом деле, @Джеймс МакНеллис прав; как только вы вызвали неопределенное поведение путем создания экземпляра vector<const int>
, обычные правила перестают иметь значение, поэтому реализация по-прежнему соответствует стандарту, что бы она ни делала - включая удаление const
из типа элемента или генерацию обычных носовых демонов.