G++ 编译器无法编译完全定义的类型

g++ compiler can't compile fully defined types

本文关键字:定义 类型 编译 编译器 G++      更新时间:2023-10-16

我正在尝试在同一结构中使用结构的静态实例,但 g++ 编译器告诉我:

C:Tempcs2cpp_triestesttest.cpp: In instantiation of 'struct Static<Test<int> >':
C:Tempcs2cpp_triestesttest.cpp:16:19:   required from 'struct Test<int>'
C:Tempcs2cpp_triestesttest.cpp:20:12:   required from here
C:Tempcs2cpp_triestesttest.cpp:6:4: error: 'Static<T>::t' has incomplete type
T t;
^
C:Tempcs2cpp_triestesttest.cpp:10:8: note: declaration of 'struct Test<int>'
struct Test
^~~~

下面是代码示例。你可以看到类型是定义的,但 g++ 仍然不喜欢它。

#include <iostream>
template < typename T >
struct Static
{
T t;
};
template < typename T >
struct Test
{
static Static<Test<T>> t;
};
template < typename T >
Static< Test<T> > Test<T>::t;
int main (int argc, char **argv)
{
Test<int> t;
return 0;
}

但是,如果从测试类中删除template < typename T >并且代码变得完全可编译

#include <iostream>
template < typename T >
struct Static
{
T t;
};
struct Test
{
static Static<Test> t;
};
Static< Test > Test::t;
int main (int argc, char **argv)
{
Test t;
return 0;
}

看起来像一个 gcc 错误,来自 [class.static]

非内联静态数据成员在其类定义中的声明不是定义,并且可能是 cv void 以外的不完整类型。

因此,无论Test<T>Static<Test<T>>是否具有完整类型,都应允许声明。

从 [温度]

当在需要完全定义的对象类型的上下文中引用类模板专用化时,将隐式实例化类模板专用化

类模板专用化的隐式实例化会导致声明的隐式实例化,

但不是定义的隐式实例化,[...] 静态数据成员 [...]

意味着当我们第一次使用Test<int>声明变量时,Test<int>必须是完全定义的类型,因此Test<int>是隐式实例化的,但Static<Test<int>>不需要是完全定义的对象类型,因为它仍然只是声明。

有趣的是,gcc 编译得很好

template<typename>
struct Static;
template<typename T>
struct Test
{
static Static<Test<T>> t;
};
template<typename T>
Static<Test<T>> Test<T>::t;
Test<int> t;
//auto u = t.t;  // error, now requires a completely-defined type

即使Static甚至没有定义,Test::t也不需要是完全定义的类型。