'why does c++ unique_ptr with incomplete types compile?

I want to use unique_ptr with an incomplete type. The code below does what I expected and can't compile.

#include <memory>
struct bar;
struct foo {
    foo() {

    }
    ~foo() {

    }
    std::unique_ptr<bar> pb{};
};
int main() {
    foo f;
}

However, if I add the definition of bar after the function main's definition. It can compile.

#include <memory>
struct bar;
struct foo {
    foo() {

    }
    ~foo() {

    }
    std::unique_ptr<bar> pb{};
};
int main() {
    foo f;
}

struct bar {

};

I have no idea why the definition after main can help main compile. Is that behavior defined in c++ standard?

c++


Solution 1:[1]

The first program is ill-formed. The second program is ill-formed, no diagnostic required.

std::unique_ptr does allow instantiation with an incomplete type, which is why using it as a member in foo is ok.

However both the definitions of the constructor and destructor of foo potentially invoke the destructor of pb which in turn invokes the default deleter std::default_delete<bar>. This requires bar to be a complete type.

This means you must make bar complete before you define the two functions. So you need to define them outside the class and put the definition of bar before both of these definitions:

#include <memory>

struct bar;

struct foo {
    foo();
    ~foo();
    std::unique_ptr<bar> pb{};
};

struct bar {
};

foo::foo() { }
foo::~foo() { }

int main() {
    foo f;
}

In the first program the default deleter's operator() will be implicitly instantiated, but bar will be incomplete at all possible points-of-instantiation, so that the compiler is required to diagnose the issue, e.g. with an error message.

In the second program, there is a possible point-of-instantiation at the end of the translation unit (in addition to the point explained above) where bar is complete. A diagnostic is not required if two possible points-of-instantiation would give different results.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1