Ошибка компиляции с помощью gcc при инициализации в классе unique_ptr неполного типа значением nullptr

Я пишу код, используя идиому pimpl с unique_ptr. Когда я попытался использовать инициализацию класса, чтобы установить для unique_ptr значение nullptr по умолчанию, gcc выдал ошибку компиляции, в то время как clang и msvc успешно скомпилировали код. И если я не использовал инициализацию в классе, ошибка исчезла.

// 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;
}

Когда я скомпилировал приведенный выше код, gcc пожаловался на «ошибку: недопустимое применение« sizeof »к неполному типу« B »». Я пробовал как gcc 8.3, так и gcc 9.1 безуспешно. Это ошибка компилятора? Спасибо!

Изменить: я попробовал, как предложил @eerorika. Если заголовочный и исходный файлы объединены в один файл, он может компилироваться обычным образом, но не разделен.

Изменить. Подтверждено, что это ошибка компилятора и уже исправлена ​​в gcc9.2.


person X. Sun    schedule 14.10.2019    source источник
comment
Компилирует файл здесь (GCC 9.2.1). Но не работает, как вы описываете, с GCC 8, поэтому, вероятно, ошибка, которая с тех пор была исправлена.   -  person Toby Speight    schedule 14.10.2019
comment
Поскольку инициализация излишняя, используйте более простую и менее подробную форму, которая работает.   -  person Phil1970    schedule 14.10.2019
comment
(...), но не разделены. Вы пробовали в A.h определить деструктор, т.е. ~A() = default;?   -  person Amadeus    schedule 16.10.2019
comment
@Amadeus Это определенно приведет к ошибке компиляции, см. stackoverflow.com/questions/9954518/. Было подтверждено, что это ошибка компилятора, и она исправлена. Подробнее см. Ответ eerorika.   -  person X. Sun    schedule 16.10.2019


Ответы (1)


Программа, и, в частности, инициализатор элемента по умолчанию, сформирована правильно. Если компилятор отказывается компилироваться, то, насколько я могу судить, это ошибка компилятора.

Я могу воспроизвести проблему с GCC 9.1, но не с 9.2 или стволом, так что, похоже, она исправлена. В более старых версиях вам может потребоваться отказаться от использования инициализатора члена по умолчанию в качестве временного решения.

person eerorika    schedule 14.10.2019
comment
Спасибо за помощь, но я не уверен в результате. Вы объединили 3 файла в один, я попробовал то же самое на своем компьютере, и он был скомпилирован, но если я разделю их на заголовочные и исходные файлы, как это было изначально, и ошибка вернулась. - person X. Sun; 14.10.2019
comment
@ X.Sun достаточно хорошо; кажется, что он воспроизводится. К сожалению, разделить ЕП в онлайн-инструментах непросто. - person eerorika; 14.10.2019