In cases where you'd like to hide the implementation of a class inside an inner class and keep a unique_ptr
to an instance of that inner class (the pimpl idiom) you need to move the default
destructor definition out of the class definition since unique_ptr
can't work with incomplete types.
Example:
A.hpp (the header a user of the class will include)
#pragma once
#include <memory>
class A {
public:
A();
~A();
void foo() const;
private:
struct A_impl; // just forward declared
std::unique_ptr<A_impl> pimpl;
};
A_impl.hpp ("hidden" - not to be included in normal usage of A
)
#pragma once
#include "A.hpp"
struct A::A_impl {
void foo() const;
};
A.cpp
#include "A_impl.hpp"
A::A() : pimpl(std::make_unique<A_impl>()) {}
A::~A() = default; // <- moved to after A_impl is fully defined
void A::foo() const { pimpl->foo(); }
A_impl.cpp
#include "A_impl.hpp"
#include <iostream>
void A::A_impl::foo() const { std::cout << "foo\n"; }
Demo
If you let the compiler generate A::~A()
it will not compile. My compiler says:
unique_ptr.h:79:16: error: invalid application of ‘sizeof’ to incomplete type ‘A::A_impl’
static_assert(sizeof(_Tp)>0,
^~~~~~~~~~~
Demo