可以"incomplete"类模板的嵌套类

Nested class of class template can be "incomplete"

本文关键字:嵌套 可以 incomplete      更新时间:2023-10-16

我不知道如何解释为什么在类模板中创建成员inner是有效的OuterTempl<T>而在非模板化类Outer中创建是非法的。

// Non-template version
struct Outer
{
    struct Inner;
    Inner inner;   // incomplete type (I get this)
};
struct Outer::Inner
{
};
// Template version
template<typename T>
struct OuterTempl
{
    struct InnerTempl;
    InnerTempl inner; // OK ... Huh!?
};
template<typename T>
struct OuterTempl<T>::InnerTempl
{
};
int main()
{
}

另请参阅IDONE。

是的

- 考虑 [temp.mem.class]/1:

模板的成员类可以在类外部定义 在其中声明它的模板定义。
[ 注:会员 类必须在首次使用之前定义,这需要 实例化 (14.7.1)。例如

template<class T> struct A {
    class B;
};
A<int>::B* b1;  // OK: requires A to be defined but not A::B
template<class T> class A<T>::B { };
A<int>::B b2;   // OK: requires A::B to be defined

— 尾注 ]

同样重要的是要提到,inner的定义构成了上述注释描述Inner的使用,只有在需要时才实例化:

除非成员 [...] 已被显式实例化或显式专业化,否则专业化 的成员在专用化 在需要成员定义的上下文中引用;

由于代码中不存在OuterTempl的实例化,因此永远不会实例化inner的定义,也永远不需要实例化Inner。因此,只有在实例化时才需要此类声明的嵌套类类型的完整性。您不会在此处实例化OuterTempl,但是如果您在定义Inner之前执行此操作,则代码格式不正确。

那是

template<typename T>
struct OuterTempl
{
    struct InnerTempl;
    InnerTempl inner;
};
template struct OuterTempl<int>; // Bad - Ill-formed (NDR?)
template<typename T>
struct OuterTempl<T>::InnerTempl {};
template struct OuterTempl<int>; // Fine

演示

定义类时需要定义成员类型。但是,类模板在实例化之前不会定义。在此之前,任何类型的依赖类型都可以更改。仅当类实例化时,才需要成员的定义。

另一方面,非模板类的定义是一个定义,它需要知道此时其成员的大小。