I have a piece of generic code that, when instantiated, boils down to:
struct A{...};
A f1(){
A ret;
std::pair<A&, int> p(ret, 1);
p = g(); // g returns a pair<A, int>, but I am not interested in g
return ret; // RVO :)
};
As far as I understand, this will work with RVO.
The question is, would this other code return the object of type A
with RVO?
A f2(){
std::pair<A, int> p;
p = g();
return p.first; // RVO ?
};
I understand that since the return object is obscured, it will not do RVO or that the compiler may not be able to pick the "optimization". But I don't see a fundamental reason why it wouldn't be possible, in other words, I think for consistency, it should do RVO (which I want).
The reason I ask, it because I think f2
is more elegant code than f1
.
Should this last version do RVO? If so, is it compiler dependent?
My crude test with gcc 8.1 gives that RVO doesn't work in f2
and f3
below:
struct A{
double something;
A() = default;
A(A const& other) : something(other.something){std::cerr << "cc" << '\n';}
A(A&& other) : something(other.something){std::cerr << "mc" << '\n';}
};
A f1(){
A ret;
std::pair<A&, int> p(ret, 1);
p.first.something = 5.;
return ret; // RVO :)
};
A f2(){
std::pair<A, int> p;//(ret, 1);
p.first.something = 5.;
return p.first; // no RVO :(
};
A f3(){
std::pair<A, int> p;//(ret, 1);
p.first.something = 5.;
return std::move(p).first; // no RVO :(
};
int main(){
A a1 = f1(); // prints nothing, RVO
A a2 = f2(); // prints "cc"; no RVO! Why?
A a3 = f3(); // prints "mc" (no much gain in this case); still no RVO!
}