The following https://godbolt.org/z/5qd8WbYz9 doesn't work and after reading the duplicate I thought I would have to define an custom deleter
However, I managed to get it working https://godbolt.org/z/dzYvsdKP1 by
- adding a default constructor implemented in
BB.cpp(to avoid implicit in-class default constructor) - removing the
{nullptr}in-class initialization of theunique_ptr
Can someone explain why the {nullptr} make's it break?
It's important to note that std::default_deleter<AA> can be instantiated even when AA is incomplete.
//BB.h
#include <memory>
struct AA;
struct BB
{
// B(); <- needed
~BB();
std::unique_ptr<AA> u{ nullptr }; // need to remove {nullptr} initializer
};
// BB.cpp
#include "BB.h"
struct AA {};
BB::~BB() = default;
// BB::BB() = default; <- needed
// main.cpp
#include "BB.h"
int main()
{
BB bb{};
}
AAcan not be an incomplete type at the timeBB::~BBis defined sinceAAmust be a complete type at the timestd::default_delete::operator()is called (which will happen inBB::~BB. Otherwise, the program is ill-formed.cppreference:
The situation is the same as when you are implementing something using the pimpl idiom.
AAcan be incomplete when definingBB.AAmust be complete when definingBB::~BB.BB::BBimplicitly defined or= defaulted triggers astatic_assertbydefault_deletein g++ and clang++ since it would then need to defineunique_ptr<AA, default_delete<AA>>s destructor too early:BBmember functions untilAAis defined is the idiomatic solution.