2013-05-02 2 views
5

После того, как я почесал голову на некоторых ошибках в некотором шаблоне кода, который использовал std::vector::value_type, я отследил его до следующего. Является ли это правильным поведением в соответствии со стандартом, или это проблема с MSVC 2012 CTP?Правильное поведение для std :: vector <T> :: value_type

typedef std::vector<int>::value_type  t1; 
typedef std::vector<int const>::value_type t2; 

static_assert(!std::is_same<t1, t2>::value, "hmmm"); 

Вышеуказанное утверждение не выполнено.

+1

IMO Я бы ожидал 'std :: vector' (и других контейнеров)' std :: remove_const' для своего 'value_type', но это, как представляется, показывает, что они этого не делают. Да. –

+3

@MooingDuck: Нет. В соответствии со стандартом 'value_type' является просто' T'. Он не устраняет константу. – Nawaz

+1

Вопрос в следующем: 'std :: vector ' разрешено? – Nawaz

ответ

9

value_type of std::vector<T> является T (§23.3.6.1).

Значение is_same учитывает квалификаторы cv (§20.9.6).

В вашем случае это означает, что проверка std::is_same<int, int const>, которая, как предполагается, терпит неудачу.

Это, в свою очередь, означает, что поведение, которое вы наблюдаете, неверно в соответствии со стандартом. Кажется, что MSVC снижается отборочные резюме для value_type:

std::vector<const int>::value_type val = 5; 
val = 10; 

Это компилирует на msvc2008, но не с помощью GCC 4.4.

Возможно, вы должны сообщить об ошибке в Microsoft.

Редактировать: Комментарий Наваза выше заставил меня думать. Согласно this questionconst int действительно не разрешено как значение_type в C++ 03! Кажется, что это в C++ 11. . Хотя это не запрещено в C++ 11 для векторов, для распределителей (§17.6.3.5) запрещено, что, в свою очередь, делает его незаконным и для векторов.

В любом случае, поведение MSVC в молчании, опуская const, кажется неправильным.

+0

Я чувствую себя пустым после прочтения этого ... Это потрясающая работа по исследованию здесь! – Gui13

+2

Хотя ваши ожидания имеют смысл для меня, AFAIK, 'std :: vector ' is ** not ** стандартизован. Поэтому Microsoft может реализовать его как ** расширение ** (которое GCC не делает), лишая 'const' от' const int'. –

+0

Я думаю, вы могли бы утверждать, что это стандартное поведение по стандарту, и поэтому Microsoft имеет право делать все как угодно. Я все еще задаюсь вопросом, является ли нынешнее поведение преднамеренным, или оно просто там, потому что никто не жаловался на это раньше. – ComicSansMS

1

Мне кажется std::vector<const int> не допускается: согласно стандарту T должно быть CopyInsertable и const int нет.

См. Требования к контейнерам для последовательности по 23.2.3. Контейнеры последовательности [sequence.reqmts] в осадке N3485.

ОП код не компилировать как с GCC 4.7 и КМК 13,0 на линии

typedef std::vector<int const>::value_type t2;

Судя по всему, MSVC отбрасывает константным спецификатором.

3

GCC 4.7.2, например, не скомпилирует код OP еще до того, как он достигнет static_assert.

Проблема заключается в том, что стандартные контейнеры (например, std::vector) не были предназначены для хранения const T, потому что они зависят от распределителей и стандарт в [allocator.requirements] определяет только поведение для распределителя неконстантных, отличных от исходных типов объектов.

Насколько я понимаю, это означает, что использование std::vector<const int> дает неопределенное поведение. Поэтому оба компилятора правы!

Смотрите также this вопрос, this ответ и комментарий Говарда Hinnant на нем, которое я цитирую первый sencence:

Итог: Мы не дизайн контейнеров, чтобы держать const T.

Смежные вопросы