Ответ 1
Обновление: пропустите первую часть этого ответа и перейдите к концу, который имеет лучшее решение.
Оберните дополнительную работу в новый тип и унаследуйте от него:
class A;
struct EW
{
EW(EW&&);
};
class A : private EW
{
friend class EW;
public:
A(A&&) = default;
};
EW::EW(EW&&) { A* self = static_cast<A*>(this); self->some_extra_work(); }
Вы также могли бы сделать это с элементом данных вместо базового класса, но вам нужны немного повозки, запряженные волы, используя offsetof
(который не определен для типов нестандартной верстки) или скрученных вручную эквивалент с использованием скрытой арифметики указателей. Использование наследования позволяет использовать static_cast
для конвертации.
Это не будет работать, если some_extra_work()
должно быть выполнено после инициализации членов, потому что базовые классы инициализируются первыми.
В качестве альтернативы, если дополнительная работа на самом деле работает с объектом rvalue, из которого вы перемещаетесь, то вам следует обернуть элементы в типы, которые выполняют эту работу автоматически при перемещении из, например, мой тип tidy_ptr, который я использую для реализации правила нуля
class A
{
tidy_ptr<D> d;
public:
A() = default;
A(const A&) = default;
A(A&& r) = default; // Postcondition: r.d == nullptr
};