4LegsDrivenCat
4LegsDrivenCat

Reputation: 1361

Structured binding with map in range-based loop captures by reference instead of value

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

Answers (1)

Sam Varshavchik
Sam Varshavchik

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

Related Questions