Inappropriate type completeness in template base class destructor

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

Consider the following case:

#include <memory>

struct Foo;

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

int main() {
    Bar b;
}

      

In GCC and Clang, compiling this as an independent TU throws 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, Clang one is similar and both point to the definition struct Bar

. Also, adding the missing definitions after main()

fixes the error:

// Same as above

struct Foo { };

Bar::~Bar() = default;

      

It doesn't seem right to me that the descriptor std::unique_ptr

should be created correctly when defined Bar

, since it is only called by a Bar

destructor that is defined outside of the string.

I find it even weirder that adding definitions after everything else where they shouldn't be available seems to fix the problem.

If the first snippet is correct, and if not, why not? What happens in the second that fixes it?

+3


source to share





All Articles