const decltype (* std :: begin (container)) & val не создает val const? - PullRequest
4 голосов
/ 17 ноября 2011

Этот фрагмент кода:

std::vector <int> ints(5,1);
std::for_each(ints.begin(), ints.end(), [](const decltype(*std::begin(ints))& val){ val*=2; });

компилируется и прекрасно работает в Visual Studio 2010 и изменяет каждое значение в контейнере, как если бы не было ключевого слова const.Это ошибка в компиляторе, поскольку ожидаемое поведение заключается в том, что val не модифицируется?(другими словами, я ожидаю, что это не скомпилируется, но это происходит)

Обновление:

std::for_each(ints.begin(), ints.end(), [](const std::remove_reference<decltype(*std::begin(ints))>::type& val){ val*=2; });

, кажется, ведет себя правильно, хотяне делай меня умнее.

Примечание:

decltype(*std::begin(ints)) является ссылкой на int.

1 Ответ

8 голосов
/ 17 ноября 2011

Похоже, компилятор пытается применить const к int&, что делает его int& const, что является излишним, так как ссылка не может быть переустановлена ​​в любом случае 1) .Попробуйте поместить константу между decltype и ссылкой: decltype(*ints.begin()) const&

1) Спасибо за комментарии для разъяснения.

Удалите это, благодаря комментарию @ Бена Iзаметил реальную проблему.Попробуйте decltype(*ints.cbegin()).cbegin возвращает const_iterator, который разыменовывает ссылку на const.Кроме того, нет необходимости в дополнительном амперсанде, так как *ints.cbegin() уже возвращает int const&.

Чтобы объяснить, что пошло не так в коде OP, это просто, как @Ben Voigt говорит в комментариях: decltype(*std::begin(ints))разрешается в int&, поскольку std::begin(ints) возвращает неконстантный итератор для неконстантных контейнеров, а разыменование такого итератора возвращает ссылку на неконстантное.

...