我刚才发现C ++在下面的代码中需要一个typename(请参阅代码片段末尾的成员函数定义):
template <typename T> struct ClassWithSubtype
{
struct Sub
{
//static void check( const ClassWithSubtype<T>::Sub& sub );
ClassWithSubtype<T>::Sub& operator=( const ClassWithSubtype<T>::Sub& other );
};
};
/*
//Here C++ does not require a typename for the argument type
template <typename T> void ClassWithSubtype<T>::Sub::check( const ClassWithSubtype<T>::Sub& sub )
{
//do sth.
}
*/
//Here C++ requires a typename for the return type
template <typename T> typename ClassWithSubtype<T>::Sub& ClassWithSubtype<T>::Sub::operator=( const ClassWithSubtype<T>::Sub& other )
{
//do sth.
}
我完全可以理解C ++需要关键字typename
作为返回类型。我不明白的是为什么示例函数typename
的参数类型(注释掉)需要NO check
。此外,为什么在赋值运算符的定义中需要typename
,而不是在其声明中?
答案 0 :(得分:2)
这两个规则(均在14.6.2.1中)产生观察到的行为:
首先,那个
名称是指当前实例化,如果它是
在类模板的定义,类模板的嵌套类,类模板的成员或类模板的嵌套类的成员中,注入类名(第9条)类模板或嵌套类
在主类模板或主类模板成员的定义中,类模板的名称后跟主模板的模板参数列表(如下所述) 括在
<>
(或等效的模板别名专门化),在类模板的嵌套类的定义中,嵌套类的名称被引用为 当前实例化的成员,或
还有一个不相关的要点。
然后,
如果名称是
,则该名称是当前实例化的成员
- 一个非限定名称,当查找时,指的是当前实例化或其非依赖基类的类的至少一个成员。 [注意:只有在类模板定义所包含的范围内查找名称时才会出现这种情况。 - 结束注释]
和两个不相关的要点。
因此,在这两种情况下,ClassWithSubType<T>
都指当前的实例化。但正如本说明所解释的那样,Sub
仅在类模板体内使用时才引用当前实例化的成员。在课外定义中,它成为未知专业化的成员&#34;。
作为当前实例化的成员,编译器确定Sub
是类类型。
在类体之外,编译器不知道这一点,并且需要typename
关键字。