Если я использую unique_ptr<T>
для создания класса pimpl, я понимаю, что сгенерированные компилятором функции, вызывающие деструктор T
, требуют, чтобы T
был полным типом. Но как насчет конструктора перемещения класса pimpl? Версия, созданная компилятором, просто вызывает конструктор перемещения unique_ptr
. Эта функция ничего не разрушает. Кроме того, сгенерированный конструктор перемещения класса pimpl неявно является noexcept
, поэтому его тело не может генерировать исключение, которое заставило бы его отступить и уничтожить подобъект unique_ptr
.
Похоже, что следующий код должен компилироваться:
#include <memory>
class Widget { // has implicit move ctor
struct Impl;
std::unique_ptr<Impl> pImpl;
};
int main()
{
Widget *pw1 = nullptr;
new Widget(std::move(*pw1)); // call move ctor. Rejected by
} // gcc, clang, and MSVC
Как говорится в комментарии, этот код отвергается всеми gcc, clang и MSVC. Каждый жалуется на некорректную операцию с неполным типом. Это требуется стандартом? Если да, то в какой части?
Обратите внимание, что проблема здесь заключается в компиляции, поэтому неопределенное поведение во время выполнения приведенного выше кода из-за разыменования нулевого указателя pw1
не имеет значения. По той же причине утечка памяти, возникающая из-за вызова new
в последнем операторе, не важна.