Quoted from C++ Primer
if we explicitly ask the compiler to generate a move operation by using
= default
, and the compiler is unable to move all the members, then the move operation will be defined as deletedthe move constructor is defined as deleted if the class has a member that defines its own copy constructor but does not also define a move constructor, or if the class has a member that doesn’t define its own copy operations and for which the compiler is unable to synthesize a move constructor
Some code seems to violate this rule:
#include <utility>
#include <iostream>
struct X {
X() = default;
X(const X&) { std::cout << "X(const X&)" << std::endl; }
int i;
};
struct hasX {
hasX() = default;
hasX(const hasX &) = delete;
hasX(hasX &&) = default;
X mem;
};
int main()
{
hasX hx, hx2 = std::move(hx); //output is X(const X&)
}
X
doesn't define move constructor and compiler can't synthesize one for it.
According to the rule above, hasX
's move constructor is deleted.
However, because hasX
's copy constructor is deleted, hx2 = std::move(hx)
must call move constructor to output "X(const X&)"
, which shows hasX
's move constructor is defined and it use X
's copy constructor to "move". This seems to violate the rule above.
So, is't defined in C++ standard or just a compiler implementation?
Compiler I tested: VS2015 and a online compiler
Thank you for help!