Range based for loop through non-const literal c++

Viewed 258

Compiler context: I am compiling with GDB v8.3 Ubuntu with options g++ -Im -O2 -std=c++0x.

Very frequently I need to complete some loop for two or three objects so I use wrap the expression in a range based for loop with a containing litteral.

In Python3 this would look like:

a = [1,2,3]
b = [4,5,6]

for v in (a,b):
    func(v)

In c++ this obviously isn't so simple. As far as I am aware, using {a,b} creates some type of initializer list, therefor casting does not properly work. In my attempts I come to something of this sort, but do no understand how I would properly pass by reference and also have it be mutable, as my compiler complains this is neccessarily const.

vector<int> a {1,2,3};
vector<int> b {4,5,6};

for(auto& v: {a,b}) // error non-const
    func(v);
2 Answers

Based on your python program, it appears that you want to iterate through all the vectors, but with a mutable reference to each vector. You can do this by using pointers:

for(auto *v: {&a, &b})  // iterate over pointers to the vectors
    func(*v);           // dereference the pointers to get mutable
                        // references to the vectors 

Here's a demo.

int x,y;
for(int& i:{std::ref(x),std::ref(y)}){
    i=7;
}

auto& won't work, and you do have to repeat std::ref for each element.

Another trick is:

auto action=[&](auto&foo){
  // code
};
action(v1);
action(v2);

You can write:

void foreach_arg(auto&&f, auto&&...args){
  ((void)f(decltype(args)(args)),...);
}

or pre- versions in more characters, then:

auto action=[&](auto&foo){
  // code
};
foreach_arg(action, v1, v2);

If you want the arguments mentioned first, you can do:

auto foreacher(auto&&...args){
  return [&](auto&&f){
    ((void)f(decltype(args)(args)),...);
  };
}

and get:

foreacher(v1,v2)([&](auto&v){
  // loop body
});

apologies for any typos. Just writing insomnia-code, untested as yet.

decltype thing is a short std::forward equivalent in this case (with auto&& args; with some other declarations it doesn't work).

auto arguments to functions are a thing.

Then,... is comma-fold execute, a thing.

auto arguments to lambdas are a thing.

All can be replaced with constructs (in this case) at the cost of a lot more verbosity.

Related