Inconsistent type completeness in the destructor of a template base class

Viewed 87

Please ignore the dubious inheritance pattern from a design point of view. Thanks :)

Consider the following case:

#include <memory>

struct Foo;

struct Bar : std::unique_ptr<Foo> {
    ~Bar();
};

int main() {
    Bar b;
}

In both GCC and Clang, compiling this as an independent TU raises an error:

In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = Foo]':
  required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = Foo; _Dp = std::default_delete<Foo>]'
error: invalid application of 'sizeof' to incomplete type 'Foo'
  static_assert(sizeof(_Tp)>0,
                      ^

This is GCC's, Clang's one is similar, and both point at the definition of struct Bar. Additionally, adding the missing definitions after main() fixes the error:

// Same as above

struct Foo { };

Bar::~Bar() = default;

It doesn't sound right to me that std::unique_ptr's destructor needs to be instantiated right when defining Bar, since it is only called by Bar's destructor which is defined out-of-line.

I find it even weirder that adding the definitions after everything else , where they shouldn't be reachable, apparently fixes the problem.

Should the first snippet be correct, and if not, why? What's happening in the second one that fixes it?

0 Answers
Related