Требуется ли для конструктора перемещения в классе pimpl на основе unique_ptr полный тип?

Если я использую 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 в последнем операторе, не важна.


person KnowItAllWannabe    schedule 09.01.2016    source источник


Ответы (1)


Так близко.

Кроме того, сгенерированный конструктор перемещения класса pimpl неявно имеет значение noexcept, поэтому его тело не может генерировать исключение, которое заставило бы его отступить и уничтожить подобъект unique_ptr.

[class.base.init] / 12:

В конструкторе без делегирования деструктор для каждого потенциально сконструированного подобъекта типа класса потенциально вызывается (12.4). [Примечание: это положение гарантирует, что деструкторы могут быть вызваны для полностью сконструированных подобъектов в случае возникновения исключения (15.2). - конец примечания]

Это odr-use ([basic.def.odr] / 3) и поэтому вызывает неявное создание экземпляра деструктора unique_ptr, который, в свою очередь, в конечном итоге требует полного типа.

Для конструктора noexcept нет особого случая.

person T.C.    schedule 09.01.2016
comment
Замечательно, спасибо за ссылку. (Это [class.base.init] / 10 в C ++ 14.) Вы случайно не знаете, поднималась ли проблема по этому поводу и его влиянию на noexcept конструкторы? - person KnowItAllWannabe; 09.01.2016
comment
Теперь я вижу, что возникла проблема поднял вопрос об этом и его влиянии на noexcept конструкторы? - person KnowItAllWannabe; 09.01.2016
comment
@KnowItAllWannabe Да, он был отправлен в EWG, но, вероятно, потребуется время, чтобы EWG добралась до него. В протоколах недавних заседаний комитета говорится, что они были завалены бумагами и у них не было времени рассмотреть вопросы. - person T.C.; 09.01.2016