Search code examples
c++c++11pimpl-idiom

unique_ptr pimpl and incomplete types


This is not a dupe of std::unique_ptr with an incomplete type won't compile.

Consider the code below:

#include <memory>

struct X
{
    X();
    ~X();    

    struct Impl; 
    std::unique_ptr<Impl> up_;
};

struct Impl {}; // fully visible here

X::X() : up_{nullptr}{}
X::~X() = default;

int main()
{
    X x;
}

Live on Coliru

gcc/clang both spit an error saying that Impl is incomplete. However, I provide a default destructor for X after Impl is fully visible, so IMO the code should compile. Why doesn't? Now comes the surprise: If I make Impl an inner class, i.e. define

struct X::Impl{};

instead, then the code compiles, even without providing a destructor. Why is this happening? Shouldn't we provide such a default destructor, at least according to the link mentioned in the first line?


Solution

  • You have two different structs named Impl.

    struct X
    {
        struct Impl; // Here you declare X::Impl
        std::unique_ptr<Impl> up_;  // Here you create a pointer to a X::Impl
    };
    
    struct Impl {};  // Here you declare and define ::Impl
    
    ...
    
    int main()
    {
        X x;  // Here X::Impl is still incomplete
    }