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?
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With