下面的代码编译正常(参见下面的 Golbolt 链接):
#include <memory>
struct B;
struct A1 {
A1() = default;
~A1();
std::unique_ptr<B> ptr;
};
#if 0
struct A2 {
A2();
~A2();
std::unique_ptr<B> ptr;
};
A2::A2() = default;
#endif
int main()
{
}
但如果我更换#if 0
with #if 1
编译类A2
我从 gcc 收到以下错误:
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/memory:76,
from <source>:1:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = B]':
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h:396:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = B; _Dp = std::default_delete<B>]'
<source>:17:1: required from here
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h:93:23: error: invalid application of 'sizeof' to incomplete type 'B'
93 | static_assert(sizeof(_Tp)>0,
| ^~~~~~~~~~~
ASM generation compiler returned: 1
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/memory:76,
from <source>:1:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = B]':
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h:396:17: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = B; _Dp = std::default_delete<B>]'
<source>:17:1: required from here
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/unique_ptr.h:93:23: error: invalid application of 'sizeof' to incomplete type 'B'
93 | static_assert(sizeof(_Tp)>0,
| ^~~~~~~~~~~
Execution build compiler returned: 1
Godbolt https://godbolt.org/z/nGdE3qnov
我在 MSVC 上得到了类似的结果。
无论我编译为 C++17 还是 C++20,我都会得到这个结果。
我的问题:
之间唯一的区别A1
and A2
是类定义内部或外部的构造函数的定义(在这两种情况下,它都定义为default
).
为何本案有差异?
这个问题是这篇文章的后续问题:为什么 unique_ptr 需要构造函数中的完整类型? https://stackoverflow.com/questions/75408648/why-unique-ptr-requires-complete-type-in-constructor?noredirect=1#comment133056692_75408648.