This is a follow up to Is -Wreturn-std-move clang warning correct in case of objects in the same hierarchy?, because I don't understand reasoning in certain specific cases.
struct Field {
Field();
// Field(const Field&); // (a)
int a[1000000];
};
struct Base
{
Base();
// Base(const Base&); // (b)
// Base(Base&&); // (c)
Field f;
};
struct Derived : Base { };
Base foo()
{
Derived derived;
return derived;
}
As state in link answer, and in cppreference
We first consider derived as rvalue, and if it doesn't select XXX(/*const*/Derived&&)
(until C++20) then we reconsider it as lvalue.
So as long as there are no Base(Derived&&)
, a copy is done.
I didn't find the whole logic of the warning though., 1. 2. 3. should be treated the same IMO (either no warnings as currently equivalent, or warning for future proof).
For 1.
copy and move constructor are generated by compiler.
copy or move give same result at the end.
For 2.
Field
move constructor is non longer generated, making the whole chain copy instead of move.
copy or move give same result at the end.
For 3.
Base
move constructor is non longer generated, making copy from the start.
copy or move give same result at the end.
For 4.
Base has both copy and move constructor.
copy or move give different result.
For 5.
We now have match XXX(Derived&&)
(XXX
=Derieved
), so no copy done.