Reputation: 1361
In the code below I use auto (not auto&, const auto, const auto& or auto&&), but k has a reference type.
Why is it captured by reference (as GCC says) and not by value? Looks counterintuitive.
If it's captured by value (as Clang says), why it is captured as const?
What does the standard say about this?
Is there a way to capture it by non-const value (if I want to make further manipulations with k without modifying the map) or I have to make a copy of k inside the loop?
std::map<int, int> map{{3,7},{1,16}};
for (auto [k, v] : map) {
//k *= 3; // error: assignment of read-only reference 'k'
std::printf("k=%i v=%i\n", k, v);
}
GCC produces (https://godbolt.org/z/eq6c6Gxc4):
<source>:9:15: error: assignment of read-only reference 'k'
9 | k *= 3; // error: assignment of read-only reference 'k'
| ~~^~~~
Clang produces (https://godbolt.org/z/K9bcvjqs3):
<source>:9:15: error: cannot assign to variable 'k' with const-qualified type 'std::tuple_element<0, std::pair<const int, int>>::type' (aka 'const int')
9 | k *= 3; // error: assignment of read-only reference 'k'
| ~ ^
<source>:8:20: note: variable 'k' declared const here
8 | for (auto [k, v] : map) {
| ^
Upvotes: 1
Views: 1184
Reputation: 118435
If the goal here is to lose the const
with auto
type deduction, then the simplest solution is to bind by reference and make a copy yourself:
#include <map>
#include <cstdio>
int main()
{
std::map<int, int> map{{3,7},{1,16}};
for (auto &[kref, vref]: map)
{
auto k=kref, v=vref;
k *= 3; // no more error
std::printf("k=%i v=%i\n", k, v);
}
return 0;
}
It is a near certainty that today's C++ compilers will optimize away the structured bind, entirely. The end result will be the same as a single copy.
Upvotes: 0