Consider this code:
#include <iostream>
template<typename A>
struct S{
S(const A& a){
std::cout << "L\n";
}
S(A&& a){
std::cout << "R\n";
}
};
S<int> f1(){
int a = 1;
return {a};
}
S<int> f2(){
int a = 1;
return a;
}
S<int> f3(){
int a = 1;
return {std::move(a)};
}
int main()
{
f1();
f2();
f3();
}
Output is
L
R
R
As you may know C++ implicitly moves in the return (in f2). When we do it manually in the initializer list it works (f3), but it is not done automagically by C++ in f1.
Is there a good reason why this does not work, or is it just a corner case deemed not important enough to be specified by the standard?
P.S. I know compilers can (sometimes must) do RVO, but I do not see how this could explain the output.
f1
is interpreted as you explicitly constructS<int>
froma
then return it. While inf2
it is more of returna
so compiler interprets it as a move - which it would do were it to return anint
(same type asa
). – Wye