Конструктор перемещения не наследуется с using Base::Base;
так, как вам кажется, потому что конструктор перемещения в Base
не имеет сигнатуры, которую имел бы конструктор перемещения в Derived
. Первый получает Base&&
, второй - Derived&&
.
Затем в Derived
вы объявляете деструктор. Это запрещает неявное объявление конструктора перемещения для Derived
. Таким образом, в Derived
.
отсутствует конструктор перемещения. Затем компилятор возвращается к неявно сгенерированному конструктору копирования Derived
для Derived d2 = std::move(d);
. Но это определяется как удаленный, потому что базовый класс Derived
не может копироваться. (Вы вручную удалили конструктор копирования Base
.)
В разрешении перегрузки конструктор удаленных копий выбирается вместо унаследованного конструктора базовых классов Base(Base&&)
(хотя значение Derived
может связываться с Base&&
) поскольку для последнего требуется последовательность преобразования, которая не считается точным соответствием , а привязка к const Derived&
считается точным совпадением с целью разрешения перегрузки.
Также есть предложенная формулировка для разрешения CWG, проблема 2356 , которая исключит унаследованный Base
конструктор перемещения от участия в разрешении перегрузки вообще. (Из того, что я могу сказать, это то, что компилятор уже реализует.)
Если у вас нет веской причины для объявления деструктора, не делайте этого. Если у вас есть причина, вам нужно снова выполнить операции перемещения по умолчанию, как вы это делали для конструктора перемещения в Base
. (Возможно, вы захотите по умолчанию использовать оператор присваивания перемещения, если классы должны быть назначаемыми.)
Если вы намереваетесь использовать иерархию классов полиморфно, вы должны объявить виртуальный (дефолтный) деструктор в полиморфизме c base, но вам не нужно объявлять деструктор в производных классах.