Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iteration over references?

I would like to perform the same operation on several arrays, something like:

#include<vector>
#include<algorithm>
int main(void){
    std::vector<double> a, b;
    for(auto& ab:{a,b}) std::sort(ab.begin(),ab.end()); // error 
}

This code fails, since auto& is a const-reference. Is there an elegant way around it?

like image 771
eudoxos Avatar asked Feb 07 '12 11:02

eudoxos


2 Answers

I think the issue is that it's a bit like binding a temporary to a non-const reference. There is no "concrete" collection there so it is a bit like a temporary.

IF you have a temporary vector there, it will bind to a const reference but not a non-const one.

I also think this won't ever work what you are doing, but this should work:

#include<vector> 
#include<algorithm> 
int main(void)
{     
    std::vector<double> a, b;     
    for(std::vector<double>* ab:{&a,&b}) 
      std::sort(ab->begin(),ab->end()); // or begin(*ab),end(*ab)
} 

and auto may work too.

like image 107
CashCow Avatar answered Oct 24 '22 10:10

CashCow


This code fails, since auto& is a const-reference. [emphasis mine]

Your reasoning doesn't hold. In a range-based for loop, what you declare (here, auto& ab) is not bound to the range expression (here, {a,b }). Instead, ab will be initialized from the elements of the range, not the range itself.

Instead the error stems from calling std::sort with parameters ab.begin()/ab.end(), which can easily be witnessed by commenting the body of the loop. As RMartinho has pointed out, the elements of the std::initializer_list<std::vector<double>> are immutable, and you can't sort a const container (std::sort shuffles elements using moves, can't assign to a const element).

Assuming you want to (independently) sort both vectors, you can do:

for(auto& ab: { std::ref(a), std::ref(b) })
    std::sort(std::begin(ab.get()), std::end(ab.get()));

Notice that according to template argument deduction rules, auto& is fine here and auto will be deduced to const std::reference_wrapper<std::vector<double>>, yielding std::reference_wrapper<std::vector<double>> const& as the type of ab.

like image 2
Luc Danton Avatar answered Oct 24 '22 10:10

Luc Danton