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.
我不知道如何解释为什么在 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.