Nested class of class template can be “incomplete”

删除回忆录丶 提交于 2021-02-08 21:49:17

问题


I'm at a loss as to how to explain why it is valid to create the member inner in the class template OuterTempl<T> whereas it is illegal to do so in the untemplated 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()
{
}

See also ideone.


回答1:


Yes - consider [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 ]

It is also important to mention that the definition of inner, which constitutes the use of Inner the above note describes, is only instantiated once it is required:

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;

Since no instantiation of OuterTempl is present in your code, the definition of inner is never instantiated, and an instantiation of Inner is never necessitated. The completeness of the nested class type for such a declaration is thus only required at the point of instantiation. You don't instantiate OuterTempl here, but if you would do that before the definition of Inner, the code would be ill-formed.

That is,

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.




回答2:


The member types need to be defined when the class is defined. However, a class template doesn't get defined until it gets instantiated. Any kind of dependent types can change till then. The definition of members is only needed when the class gets instantiated.

On the other hand the definition of a non-template class is a definition which needs to know the size of its member at that point.



来源:https://stackoverflow.com/questions/27760896/nested-class-of-class-template-can-be-incomplete

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!