Given base class A and derived class B, A has deleted move constructor:
class A {
public:
A() {}
A(const A&) = default;
A(A&&) = delete;
};
class B : public A
{
};
In such case, the following function does not compile because of deleted move constructor:
A f() {
A a;
return a;
}
but the similar function for B does not report any error:
B g() {
B b;
return b;
}
Does it mean that move constructor in B is not deleted? I want to know what is the rule in the standard.
The move constructor in B
is deleted, but does not participate in overload resolution. According to cppreference:
The implicitly-declared or defaulted move constructor for class T is defined as deleted if any of the following is true:
- T has non-static data members that cannot be moved (have deleted, inaccessible, or ambiguous move constructors);
- T has direct or virtual base class that cannot be moved (has deleted, inaccessible, or ambiguous move constructors);
- T has direct or virtual base class or a non-static data member with a deleted or inaccessible destructor;
- T is a union-like class and has a variant member with non-trivial move constructor.
A defaulted move constructor that is deleted is ignored by overload resolution (otherwise it would prevent copy-initialization from rvalue).
The second bullet point applies: B
has a direct base class, A
, with a deleted move constructor. So B
's implicitly-declared move constructor is defined as deleted.
However, when the return statement is evaluating which constructor of B
to use, the deleted move constructor is not considered but the valid copy constructor is.