This is a follow up of this question: Does PIMPL idiom actually work using std::unique_ptr?
The full example uses multiple files, so for the sake of this question I will reduce it here. The full working example is here: https://wandbox.org/permlink/AepAJYkbRU4buDoJ and the full non-working example here: https://wandbox.org/permlink/0kP23UYJbSaUvJgS.
The shorter example is:
#include <memory>
struct A;
struct B {
~B();
std::unique_ptr<A> p = nullptr;
};
Which produces the error:
In file included from <source>:1:
In file included from /opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/memory:76:
/opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/unique_ptr.h:83:16: error: invalid application of 'sizeof' to an incomplete type 'A'
static_assert(sizeof(_Tp)>0,
^~~~~~~~~~~
/opt/compiler-explorer/gcc-11.2.0/lib/gcc/x86_64-linux-gnu/11.2.0/../../../../include/c++/11.2.0/bits/unique_ptr.h:361:4: note: in instantiation of member function 'std::default_delete<A>::operator()' requested here
get_deleter()(std::move(__ptr));
^
<source>:7:29: note: in instantiation of member function 'std::unique_ptr<A>::~unique_ptr' requested here
std::unique_ptr<A> p = nullptr;
^
<source>:3:8: note: forward declaration of 'A'
struct A;
^
1 error generated.
While using {}
compiles:
#include <memory>
struct A;
struct B {
~B();
std::unique_ptr<A> p{nullptr};
};
No errors: https://godbolt.org/z/snsfsjdqE
What is the difference? Why does std::unique_ptr<A> p = nullptr;
require to instantiate the unique_ptr
destructor, but std::unique_ptr<A> p{nullptr};
does not?
PS: I used clang for a clearer error message. Same results with gcc. All versions I tried so far.
A
is complete then there is no issue to begin with. Then it isnt a good duplicate – Placeman