In the header file:
struct some_secret_type;
struct some_public_type {
some_public_type();
~some_public_type();
private:
std::unique_ptr<some_secret_type> pImpl;
};
Then, in the cpp file:
#include <some_secret_type.h>
some_public_type::~some_public_type() = default;
some_public_type::~some_public_type() {};
Here I have explicitly declared a destructor that ended up being either empty or defaulted.
The effects of =default;
and {}
here are identical in the cpp file.
In the header file, having either a {}
or =default
would require everyone including it know what some_secret_type
looks like.
In a more general case, {}
and =default
in the header can change if a type is trivially destroyed. In the cpp/header split, they do not.
The advantage of {}
in the header is that you prevent a type from being trivial (suppose later you know you are going to make it non-trivial, and you don't want other behavior changes to happen when you do it).
In the cpp file case, {}
saves a few characters.