关于模板消歧器的问题在这里给出:
在答案中我们可以读到:
ISO C++ 03 14.2/4
当成员模板专业化的名称出现之后.或 - >在postfix-expression中,或在qualified-id中的nested-name-specifier之后,postfix-expression或qualified-id显式依赖于template-parameter(14.6.2),成员模板名称必须是以关键字模板为前缀.否则,假定该名称命名非模板.
现在我来到这个我不太明白的例子:
template <class T>
class Base {
public:
template <int v>
static int baseGet() {return v;}
class InnerA {
public:
template <int v>
static int aget() {return v;}
};
class InnerB {
public:
typedef Base BaseType;
typedef BaseType::InnerA OtherType;
template <int v>
static int baseGet() {return BaseType::baseGet<v>();} //(A)
template <int v>
static int aget() {return OtherType::aget<v>();} //(B)
};
};
Run Code Online (Sandbox Code Playgroud)
它显然无法编译.你需要template在(B)行:OtherType::template aget<v>();.然而,g ++(4.4.3)和clang ++(2.9)都没有抱怨template线(A)缺乏.为什么?BaseType取决于类型T,不是吗?这些编译器是否与标准有所不同,或者我是否误解了标准中的某些内容?
它们实现了C++ 0x规范,其中Base是当前的实例化.template在这种情况下,C++ 0x允许省略关键字.因为BaseType是一个typedef Base,当你说BaseType,它也命名当前的实例化.
引用规范,因为你似乎对spec refs感兴趣
名称是当前实例化的成员,如果它是[...]
- 一种qualified-id,其中嵌套名称指定者引用当前实例化,并且当查找时,引用当前实例化的至少一个成员或其非依赖基类.
和
名称是指当前的实例化,如果它是[...]
- 在[...] 类模板的嵌套类的定义中,类模板或嵌套类的注入类名(第9节)
和(你引用的修改后的14.2/4)
[...]或qualified-id中的nested-name-specifier引用依赖类型,但名称不是当前实例化的成员(14.6.2.1),成员模板名称必须以关键字为前缀模板.[...]
注:在C++ 03你的代码是形成不良的,因为这两个BaseType和OtherType依赖.规范说:
如果是[...],则类型取决于
- 模板参数
- 带有嵌套名称说明符的qualified-id,它包含一个命名依赖类型的类名
- template-id,其中模板名称是模板参数或任何模板参数是依赖类型
(注意,Base等同于Base<T>,其是在其上基部Base和BaseType::InnerA依赖类型).
请注意,引用中的"明确取决于"是一个预先标准的术语,并且最近被淘汰(我相信它是在1996年12月).它基本上意味着(在此上下文中)限定符所依赖的qualified-id或者依赖的类成员访问(a->x/ a.x)a.从草案中删除"明确依赖"之后,它仍然潜伏在某些地方,甚至C++ 0x仍然在14.6.2p2的注释中引用了"明确依赖":
基类名
B<T>,类型名T::A,名称,B<T>::i并pb->j明确依赖于template-parameter.