This piece of code:
std::vector <int> ints(5,1);
std::for_each(ints.begin(), ints.end(), [](const decltype(*std::begin(ints))& val){ val*=2; });
compiles and runs just fine in Visual Studio 2010, and modifies every value in the container like if the const keyword weren't there. Is this a bug in the compiler, as the expected behaviour is that val is non-modifiable? (in other words, I expect it not to compile, but it does)
Update:
std::for_each(ints.begin(), ints.end(), [](const std::remove_reference<decltype(*std::begin(ints))>::type& val){ val*=2; });
seems to behave const-correctly, however that doesn't make me smarter.
Note:
decltype(*std::begin(ints))
is a reference to an int.
It seems the compiler tries to apply the const
to the int&
, making it int& const
, which is superfluous as a reference can't be reseated anyways1). Try putting the const between the decltype
and the reference: decltype(*ints.begin()) const&
1) Thanks for the comments for the clarification.
Scrap that, thanks to @Ben's comment I noticed the real problem. Try decltype(*ints.cbegin())
. cbegin
returns a const_iterator
, which dereferences to a reference-to-const. Also, no need for the extra ampersand, as *ints.cbegin()
already returns a int const&
.
To explain what went wrong in the OP's code, it's just as @Ben Voigt says in the comments: decltype(*std::begin(ints))
resolves to int&
, since std::begin(ints)
returns a non-const iterator for non-const containers and dereferencing such an iterator returns a reference-to-non-const.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With