class 模板的嵌套 class 可以是 "incomplete"

Nested class of class template can be "incomplete"

我不知道如何解释为什么在 class 模板 OuterTempl<T> 中创建成员 inner 是有效的,而在 OuterTempl<T> 中这样做是非法的未模板化的 class 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()
{
}

另见 ideone

定义class时需要定义成员类型。但是,class 模板在实例化之前不会被定义。到那时任何类型的依赖类型都可以改变。只有在实例化 class 时才需要定义成员。

另一方面,非模板的定义class是一个需要知道其成员在该点的大小的定义。

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

A member class of a class template may be defined outside the class template definition in which it is declared.
[ Note: The member class must be defined before its first use that requires an instantiation (14.7.1). For example,

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

— end note ]

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

Unless a member […] has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist;

由于您的代码中不存在 OuterTempl 的实例化,因此永远不会实例化 inner 的定义,并且永远不需要实例化 Inner。因此,仅在实例化时才需要此类声明的嵌套 class 类型的完整性。您没有在这里实例化 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

Demo.