模板模板成员的消歧模板关键字:何时完全?

Cyg*_*sX1 2 c++ templates

关于模板消歧器的问题在这里给出:

模板消歧器

在答案中我们可以读到:

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,不是吗?这些编译器是否与标准有所不同,或者我是否误解了标准中的某些内容?

Joh*_*itb 8

它们实现了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你的代码是形成不良的,因为这两个BaseTypeOtherType依赖.规范说:

如果是[...],则类型取决于

  • 模板参数
  • 带有嵌套名称说明符的qualified-id,它包含一个命名依赖类型的类名
  • template-id,其中模板名称是模板参数或任何模板参数是依赖类型

(注意,Base等同于Base<T>,其是在其上基部BaseBaseType::InnerA依赖类型).

请注意,引用中的"明确取决于"是一个预先标准的术语,并且最近被淘汰(我相信它是在1996年12月).它基本上意味着(在此上下文中)限定符所依赖的qualified-id或者依赖的类成员访问(a->x/ a.x)a.从草案中删除"明确依赖"之后,它仍然潜伏在某些地方,甚至C++ 0x仍然在14.6.2p2的注释中引用了"明确依赖":

基类名B<T>,类型名T::A,名称,B<T>::ipb->j 明确依赖于template-parameter.