Форвардная декларация с уникальным_ptr?

Я нашел полезным использовать прямое объявление классов в сочетании с std::unique_ptr, как в приведенном ниже коде. Он компилируется и работает с GCC, но все это кажется странным, и мне интересно, является ли это стандартным поведением (т.е. Обязательным стандартом)? Поскольку B не является полным типом, когда я объявляю unique_ptr.

A.hpp

#include <memory>

class B;

class A {
    std::unique_ptr<B> myptr;
    // B::~B() can't be seen from here
public:
    ~A();
};

a.cpp

#include "B.hpp"
//B.hpp has to be included, otherwise it doesn't work.

A::~A() = default; // without this line, it won't compile 
// however, any destructor definiton will do.

Я подозреваю, что это связано с деструктором (и, следовательно, необходимость вызова деструктора unique_ptr<B>) определяется в определенном модуле компиляции (A.cpp).

Ответ 1

Это явно законно. Правило состоит в том, что типы, используемые для создания экземпляра шаблон в стандартной библиотеке должен быть завершен, если не указано иное указано. В случае unique_ptr в §20.7.1/5 говорится: "[...] параметр шаблона T уникального_ptr может быть неполным. "

Существуют определенные операции над указателем, которые требуют полного тип; в частности, когда объект будет фактически разрушен (при по крайней мере, с дефолтом по умолчанию). В вашем примере, например, если A::~A() были встроенными, это может вызвать проблемы. (Обратите внимание, что если вы не объявляйте деструктора самостоятельно, он будет встроенным. Который частично поражает цель использования std::unique_ptr.)