【问题标题】:C++ Template AmbiguityC++ 模板歧义
【发布时间】:2010-09-08 07:49:48
【问题描述】:

我和一个朋友正在讨论 C++ 模板。他问我这应该怎么做:

#include <iostream>

template <bool>
struct A {
    A(bool) { std::cout << "bool\n"; }
    A(void*) { std::cout << "void*\n"; }
};

int main() {
    A<true> *d = 0;
    const int b = 2;
    const int c = 1;
    new A< b > (c) > (d);
}

main 中的最后一行有两个合理的解析。 'b' 是模板参数还是 b &gt; (c) 模板参数?

虽然编译它很简单,看看我们得到了什么,我们想知道是什么解决了歧义?

【问题讨论】:

    标签: c++ templates grammar


    【解决方案1】:

    AFAIK 它将被编译为new A&lt;b&gt;(c) &gt; d。这是解析它恕我直言的唯一合理方法。如果解析器在正常情况下不能假设 a > 结束一个模板参数,那将导致更多的歧义。如果你想要它,你应该写:

    new A<(b > c)>(d);
    

    【讨论】:

      【解决方案2】:

      正如 Leon & Lee 所述,14.2/3 (C++ '03) 明确定义了这种行为。

      C++ '0x 通过适用于&gt;&gt; 的类似规则增加了乐趣。基本概念是,在解析模板参数列表时,非嵌套 &gt;&gt; 将被视为两个不同的 &gt; &gt; 标记,而不是右移运算符:

      template <bool>
      struct A {
        A(bool);
        A(void*);
      };
      
      template <typename T>
      class C
      {
      public:
        C (int);
      };
      
      int main() {
          A<true> *d = 0;
          const int b = 2;
          const int c = 1;
          new C <A< b  >>  (c) > (d); // #1
          new C <A< b > >  (c) > (d); // #2
      }
      

      '#1'和'#2'在上面是等价的。

      这当然解决了在嵌套特化中必须添加空格的烦恼:

      C<A<false>> c;  // Parse error in C++ '98, '03 due to "right shift operator"
      

      【讨论】:

      • 我以前听说过这个。无论如何,一些编译器已经通过允许x&lt;y&lt;z&gt;&gt; 抢先一步。但我只是想知道:它实际上是根据上下文敏感词法定义的,还是由像 TemplateId '>' 这样的语法规则本身给出的?
      • @Stewart:是前者(上下文敏感词法分析)。总而言之,14.2/3 表示在解析模板参数列表时,第一个非嵌套 >> 被视为两个单独的 > 标记。您可以阅读实际论文了解更多信息:open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html
      【解决方案3】:

      C++ 标准定义,如果模板名称后跟&lt;,则&lt; 始终是模板参数列表的开头,第一个非嵌套的&gt; 被视为模板的结尾参数列表。

      如果您打算将 &gt; 运算符的结果作为模板参数,那么您需要将表达式括在括号中。如果参数是 static_cast&lt;&gt; 或其他模板表达式的一部分,则不需要括号。

      【讨论】:

        【解决方案4】:

        词法分析器的贪婪可能是没有括号使其明确的决定因素。我猜词法分析器并不贪心。

        【讨论】:

        • 但是词法分析不是完全明确的吗?
        • 它会在歧义上出错,所以是的。贪婪或不贪婪不会让你模棱两可。贪婪实际上是一种解决歧义的方法。在这种情况下,您还涉及到词法分析器和解析器之间的交互,所以也许是解析器不贪婪。
        • 语法可能有歧义,但词法分析器绝对不是。间距使词法分析器完全定义良好。
        • 我同意你的看法。我从来没有说过词法分析器是模棱两可的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多