C++ 中的嵌套子类

Nested subclasses in C++

我正在尝试创建一个嵌套的 class,它也是其父项的子项class:

struct X { struct Y : public X {}; };

不幸的是,这在 C++ 中似乎是不允许的,因为 g++ 会产生错误

error: invalid use of incomplete type 'struct X'

但是,我的实际代码有 X 作为模板 class:

template<typename T> struct X
{ struct Y : public X {}; };

我收到同样的消息,但这次只是警告:

warning: invalid use of incomplete type 'struct X< T >'

我的问题是:为什么前一种情况不合法,而模板化情况只是给出警告?模板化版本完全按照我的预期工作(我可以创建 X<T>::Y 的实例,将它们转换为 X<T>,等等),但是警告是否意味着我不应该使用它?如果我忽略警告,我会 运行 遇到什么问题?

回答基本问题:您收到警告是因为模板尚未实例化,因此不会打扰任何人。

在这两种情况下,解决此问题的方法是在 X 的布局已知的位置定义 X::Y,因此 Y 的布局可以适当推导。你可以这样做:

struct X { struct Y; }
struct X::Y {};

从技术上讲,就编译器而言,在实例化模板 (X) 之前不需要知道基 (X) 的布局。并且模板(X)在完全定义之前可能不会被实例化。在这一点上,它的布局是已知的。

从模板中获取错误的最简单方法是尝试在 X:

中实例化 Y
template<typename T> struct X {
    struct Y : public X {};
    Y y;
};

在早期版本的编译器中,您显示的情况下没有警告,但在某些时候添加了。这是来自 GCC bugtracker 的关于警告是否虚假的讨论。不确定标准是否允许这样做,但他们的结论是不允许。

因此,标准不允许使用这两种情况,但 GCC 会继续使用后者,因为它可以。

Yam Marcovic 展示了如何以符合标准的方式定义 X::Y。 gcc bugtracker 中显示了类似的相同示例。