When you use a unique_ptr<T> for a forward declared type T, the unique_ptr destructor requires the T is complete, but the move assignment operator as well (and reset), according to this table:
https://stackoverflow.com/a/6089065/1794803
So, for your pImpl idiom, to implement it correctly, you have to declare the delete and the move assignment method (which, as side effect, marks them non-inlined):
class impl_t;
class A
{
std::unique_ptr<impl_t> p_impl;
public:
// Implement in A.cpp as A::~A() = default;
~A();
// Implemented in A.cpp as A& operator=(A&&) = default;
A& operator=(A&& he);
};
But, since std::unique_ptr is a RAII-solution for dynamic memory, and you pImpl is already inside a class, and you are forced to write a destructor anyway, isn't it better to just manage a raw pointer, since you class is already a RAII-like from the point of view of p_impl?:
class impl_t;
class A
{
impl_t* p_impl;
public:
~A(); // The destructor must be written anyway.
// The omitted move assignment destructor doesn't cause UB.
};
Isn't that a better solution? (+ defined or delete your own copy/move operator if you want to class is copyable/movable or not; but that is a "conscious choice"; however, don't writting a move assignment for unique_ptr is an error).
Using a unique_ptr only saves you for written a delete p_impl in a destructor that you have to declare anyway.
unique_ptr is an excellent choice for local dynamic objects which will be destructed even in case of exceptions, but for "attributes", you save nothing but the possibility of getting UB if you don't remember you have to rewrite the move assignment operator.