Ответ 1
virtual ~A() = default;
это пользователь, объявленный деструктором. Из-за этого у A
больше нет конструктора перемещения. Это означает return tmp;
не может переместить tmp
и, поскольку tmp
не копируется, вы получаете ошибку компилятора.
Это можно исправить двумя способами. Вы можете добавить конструктор перемещения как
struct A{
std::unique_ptr<B> x;
A() = default; // you have to add this since the move constructor was added
A(A&&) = default; // defaulted move
virtual ~A() = default;
};
или вы можете создать базовый класс, который имеет виртуальный деструктор и наследовать от него, как
struct C {
virtual ~C() = default;
};
struct A : C {
std::unique_ptr<B> x;
};
Это работает, потому что A
больше не имеет объявленного пользователем деструктора (да, C
делает, но мы заботимся только о A
), поэтому он все равно будет генерировать конструктор перемещения в A
Важной частью этого является то, что в C
нет удаленного конструктора перемещения, у него просто нет одного периода, поэтому попытка его перемещения приведет к копированию. Это означает, что C
конструктор копирования вызывается в A
неявно генерируется конструктор перемещения, так как C(std::move(A_obj_to_move_from))
будет копировать до тех пор, как он не имеет удаленный конструктор перемещения.