在-class 将不完整类型的 unique_ptr 初始化为 nullptr 时使用 gcc 编译错误
Compile error with gcc when in-class initializing unique_ptr of incomplete type to nullptr
我正在使用 unique_ptr 中的 pimpl 习语编写一些代码。当我尝试使用in-class初始化将unique_ptr默认设置为nullptr时,gcc给出了编译错误,而clang和msvc都成功编译了代码。如果我没有使用 in-class 初始化错误就消失了。
// 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 抱怨 "error: invalid application of ‘sizeof’ to incomplete type ‘B’"。我试过 gcc 8.3 和 gcc 9.1 都没有成功。这是编译器错误吗?谢谢!
编辑:
我按照@eerorika 的建议尝试了。如果头文件和源文件合并成一个文件,可以正常编译,但不能分开。
编辑
已确认为编译器错误,已在 gcc9.2 中修复。
该程序,尤其是默认成员初始化程序,格式正确。如果编译器拒绝编译,那么据我所知这是编译器中的错误。
我可以使用 GCC 9.1 重现该问题,但不能重现 9.2 或 trunk,因此它似乎已得到修复。对于旧版本,您可能需要放弃使用默认成员初始化程序作为解决方法。
我正在使用 unique_ptr 中的 pimpl 习语编写一些代码。当我尝试使用in-class初始化将unique_ptr默认设置为nullptr时,gcc给出了编译错误,而clang和msvc都成功编译了代码。如果我没有使用 in-class 初始化错误就消失了。
// 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 抱怨 "error: invalid application of ‘sizeof’ to incomplete type ‘B’"。我试过 gcc 8.3 和 gcc 9.1 都没有成功。这是编译器错误吗?谢谢!
编辑: 我按照@eerorika 的建议尝试了。如果头文件和源文件合并成一个文件,可以正常编译,但不能分开。
编辑 已确认为编译器错误,已在 gcc9.2 中修复。
该程序,尤其是默认成员初始化程序,格式正确。如果编译器拒绝编译,那么据我所知这是编译器中的错误。
我可以使用 GCC 9.1 重现该问题,但不能重现 9.2 或 trunk,因此它似乎已得到修复。对于旧版本,您可能需要放弃使用默认成员初始化程序作为解决方法。