#include <vector>
class MyContainer {
public:
std::vector<int> data;
// begin() only defined for rvalues
auto begin() && { return data.begin(); }
auto end() && { return data.end(); }
};
MyContainer container;
container.data = {1, 2, 3};
// why not working ? compile error;
for (int x : MyContainer(container)) {
std::cout << x << " ";
}
clang c++ 20 complain:
'this' argument to member function 'begin' is an lvalue, but function has rvalue ref-qualifier;
but why ? MyContainer(container)
is rvalue, it SHOULD match begin() &&
, right ?
I know using MyContainer(container).begin()
is ok, but how to use it in for range loop directly?
for iter = xxx.begin(); if xxx is rvalue, *iter return rvalue too; so, for
for (auto &&e : Container()) {
x = e; // call move directly;
}
for (auto &&e : container) {
x = e; // call copy directly;
}
it's very convenient for implements many move aware of algorithm; but seems standard not aware of it for now;
hops it update in future!
for (auto itb = move(container).begin(), ite = move(container).end(); itb != ite; ++ itb) {
x = *itb; // ok, call move;
}
for (auto &&e : container) {
x = e; // ok, call copy as it is;
}
As you can see in cppreference.com, a ranged-based for loop is equivalent to a regular for
loop, scoped with some variables defined, and with specific init-statement, condition etc.
There are some changes depending on the C++ version, but for C++20 that you use it is:
{
init-statement
auto&& /* range */ = range-initializer ;
auto /* begin */ = /* begin-expr */;
auto /* end */ = /* end-expr */;
for ( ; /* begin */ != /* end */; ++/* begin */)
{
item-declaration = */* begin */;
statement
}
}
It is a bit different in earlier C++ versions, but anyway since C++11 there is always an equivalent for a variable:
auto&& /* range */ = range-initializer ;
This variable is the one used for calling begin()
and end()
.
But it has a name and is therefore an lvalue (even if you supply an rvalue as your original range-like object).
This is the reason the compiler rejects calling the rvalue ref (&&
) qualified begin()
and end()
with it.
In order to use a ranged-based for loop you should remove the &&
qualification from them.