【问题标题】:Disambiguator template keyword for a template member of a template: when exactly?模板的模板成员的消歧器模板关键字:究竟是什么时候?
【发布时间】:2011-06-23 15:29:11
【问题描述】:

这里给出了一个关于模板消歧器的问题:

template disambiguator

在答案中我们可以阅读:

ISO C++03 14.2/4

当成员模板特化的名称出现在 .或 -> 在后缀表达式中,或在限定标识中的嵌套名称说明符之后,并且后缀表达式或限定标识显式依赖于模板参数(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)
  };
};

它显然无法编译。您需要在 (B) 行中使用 templateOtherType::template aget&lt;v&gt;();。 但是,g++ (4.4.3) 和 clang++ (2.9) 都没有抱怨 (A) 行中缺少 template。为什么? BaseType 取决于 T 的类型,不是吗?是那些编译器稍微偏离了标准,还是我误解了标准中的某些内容?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    它们实现了 C++0x 规范,其中Base当前实例化。在这种情况下,C++0x 允许省略 template 关键字。因为BaseTypeBase 的typedef,所以当你说BaseType 时,它也会命名当前的实例化。

    引用规范,因为您似乎对规范参考感兴趣

    如果名称是 [...]

    ,则名称是 当前实例化的成员
    • 其中嵌套名称说明符引用 当前实例化 并且在查找时引用当前实例化或非依赖基的至少一个成员的限定 ID类。

    如果是 [...]

    ,则名称指的是当前实例化
    • 在类模板的 [...] 嵌套类的定义中,[...],注入的类名(第 9 条)类模板或嵌套类

    和(您引用的修改后的 14.2/4)

    [...] 或qualified-id中的nested-name-specifier 指的是依赖类型,但该名称不是当前实例化的成员(14.6.2.1),成员模板名称必须加前缀通过关键字模板。 [...]


    注意:在 C++03 中,您的代码格式错误,因为 BaseTypeOtherType 都是依赖的。规范说:

    一个类型是依赖的,如果它是 [...]

    • 模板参数
    • 具有嵌套名称说明符的限定 ID,其中包含命名依赖类型的类名称
    • 模板名称是模板参数或任何模板参数是依赖类型的模板 ID

    (注意Base 等价于Base&lt;T&gt;,这是BaseBaseType::InnerA 是依赖类型的基础)。

    请注意,您引用中的“显式依赖”是一个标准术语,并且最近被删除(我相信它是在 1996 年 12 月)。它基本上意味着(在这种情况下)限定符依赖的限定ID或a依赖的类成员访问(a-&gt;x/a.x)。 “显式依赖”从草案中删除后,它仍然潜伏在某些地方,甚至 C++0x 在 14.6.2p2 的注释中仍然提到“显式依赖”:

    基类名称B&lt;T&gt;、类型名称T::A、名称B&lt;T&gt;::ipb-&gt;j显式地依赖于模板参数。

    【讨论】:

      【解决方案2】:

      因为OtherType 是一个嵌套 依赖名称,而BaseType 不是嵌套类型。

      嵌套依赖类型需要使用template

      这里的关键词是:

      • 依赖类型
      • 嵌套类型

      如果一个 type 是两者,那么你必须使用 template

      • OtherType 既是依赖类型(它依赖于T)也是嵌套类型
      • BaseType 只是依赖类型(它依赖于T)。它不是嵌套类型。

      【讨论】:

      • 根据stackoverflow.com/questions/4103756/…BaseType::OtherType:: 都是嵌套名称说明符。您实际上已经在您的范围内指定了一个命名空间这一事实并不重要......或者?
      • @Cygnus:在命名空间级别定义的类型不称为嵌套类型。
      【解决方案3】:

      BaseType 确实依赖于T 类型,但InnerB 也是如此。实际上,从BaseType&lt;T&gt; 内部的任何代码来看,它都不依赖于T

      【讨论】:

      • 既然我在Base&lt;T&gt; 内部,而你说它不依赖于T - 那我为什么需要template 行(B)?
      • @CygnusX1:这是因为您正在访问另一个内部类。内部类在 C++03 中被非常奇怪地对待,关于它们的规则没有多大逻辑意义。
      猜你喜欢
      • 2011-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多