Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Innocent range based for loop not working

The following does not compile:

#include <iostream>

int main()
{
    int a{},b{},c{},d{};

    for (auto& s : {a, b, c, d}) {
        s = 1;
    }
    std::cout << a << std::endl;
    return 0;
}

Try it on godbolt

Compiler error is: error: assignment of read-only reference 's'

Now in my actual case the list is made of member variables on a class.

Now, this doesn't work because the expression becomes an initializer_list<int> that actually copies a,b,c, and d - hence also not allowing modification.

My question is two-fold:

Is there any motivation behind not allowing to write a range-based for loop in this way ? eg. perhaps there could be a special case for naked brace expressions.

What is a syntactical neat way of fixing this type of loop ?

Something along this line would be preferred:

for (auto& s : something(a, b, c, d)) {
    s = 1;
}

I do not consider pointer indirection a good solution (that is {&a, &b, &c, &d}) - any solution should give the element reference directly when the iterator is de-referenced.

like image 445
darune Avatar asked Nov 06 '19 12:11

darune


1 Answers

Ranges are not as magic as people would like. In the end, there must be an object that the compiler can generate calls on to either a member function or free function begin() and end().

Closest you'll probably be able to come is:

#include <iostream>

int main()
{
    int a{},b{},c{},d{};

    for (auto s : {&a, &b, &c, &d} ) {
        *s = 1;
    }
    std::cout << a << "\n";
    return 0;
}
like image 83
mhhollomon Avatar answered Oct 29 '22 20:10

mhhollomon