3

I'm writing some code using pimpl idiom with unique_ptr. When I tried to use in-class initialization to set unique_ptr to nullptr by default, gcc gave a compile error, while clang and msvc both successfully compiled the code. And if I didn't use in-class initialization the error went away.

// A.h
#pragma once

#include <memory>

using namespace std;

class B;
class A
{
private:
    ////////////////////////
    // here gives the error!
    ////////////////////////
    unique_ptr<B> impl{nullptr}; // error only with gcc, 
                                 // ok with clang and msvc
    unique_ptr<B> impl2; // ok with all three

public:
    A();
    ~A();
};
// A.cpp
#include "A.h"

class B
{
private:
    int b{5};

public:
    B() = default;
    ~B() = default;
};

A::A() = default;
A::~A() = default;
// main.cpp
#include "A.h"

int main()
{
    A a;
    return 0;
}

When I compiled the above code, gcc complained "error: invalid application of ‘sizeof’ to incomplete type ‘B’". I've tried both gcc 8.3 and gcc 9.1 with no success. Is this a compiler bug? Thanks!

Edit: I tried as @eerorika suggested. If the header and source files are merged into one single file, it can compile normally, but not separated.

Edit Confirmed to be compiler bug and already fixed in gcc9.2.

X. Sun
  • 315
  • 3
  • 12
  • 1
    Compiles file here (GCC 9.2.1). But fails as you describe with GCC 8, so likely a bug that's since been fixed. – Toby Speight Oct 14 '19 at 12:48
  • As the initialization is superfluous, then use the simpler form that works and less verbose. – Phil1970 Oct 14 '19 at 14:03
  • _(...) but not separated._ Have you tried, in `A.h` define the destructor, i.e. `~A() = default;`? – Amadeus Oct 15 '19 at 22:07
  • @Amadeus That would definitely result in compile error, see https://stackoverflow.com/questions/9954518/stdunique-ptr-with-an-incomplete-type-wont-compile . This has been confirmed to be a compiler bug and fixed. See eerorika's answer for details – X. Sun Oct 16 '19 at 06:35

1 Answers1

4

The program, and the default member initialiser in particular, is well-formed. If a compiler refuses to compile, then it is a bug in the compiler as far as I can tell.

I can reproduce the problem with GCC 9.1 but not 9.2 nor trunk, so it appears to have been fixed. With older versions, you may need to give up using the default member initialiser as a workaround.

eerorika
  • 181,943
  • 10
  • 144
  • 256
  • Thanks for your help but I'm not sure about the result. You merged the 3 files into one, I tried the same on my computer and it did compiled, but if I separate them to header and source files as I originally did and the error came back. – X. Sun Oct 14 '19 at 12:20
  • @X.Sun fair enough; it does seem to reproduce. Separating the TU's is not simple on the online tools unfortunately. – eerorika Oct 14 '19 at 12:23