为什么模板ID在" A< 0> = 0"没有空间编译因为大于或等于运算符"> ="?

时间:2015-02-05 21:13:39

标签: c++ templates c++11 language-lawyer

template <int>
using A = int;

void f(A<0>=0);   // Attempting to declare a function f taking int,
                  // with the default argument 0

// Works as expected:
// void f(A<0> = 0);

这既不编译GCC 4.9.2 nor Clang 3.5 - 更不用说ICC或VC ++了。显然,>=位被解析为大于或等于运算符。但是,对于[temp.names] / 3:

,这似乎是不正确的
  

名称查找(3.4)后发现名称是模板名称或那个    operator-function-id literal-operator-id 指的是一组   重载函数的任何成员是函数模板,如果   接下来是<<始终作为分隔符    template-argument-list ,永远不会作为less-than运算符。   解析 template-argument-list 时,第一个非嵌套   > 138 被视为结束分隔符而不是a   大于运营商。 [..] [示例:

template<int i> class X { /* ...*/ };

X< 1>2 > x1; // syntax error
X<(1>2)> x2; // OK
     

- 结束示例]

     

138)一个>,其中包含dynamic_cast type-id ,   static_castreinterpret_castconst_cast,或附带的{{1}}   该   后续 template-id template-argument 被认为是为了本说明而嵌套的。

我错过了什么或者这是编译错误吗?

1 个答案:

答案 0 :(得分:18)

具有词法分析器的maximal munch principle的效果使用尽可能多的字符来形成有效的标记。这在草案C ++标准部分2.5 [lex.pptoken] 中有所说明:

  

否则,下一个预处理标记是最长的序列   可能构成预处理令牌的字符,即使这样   会导致进一步的词汇分析失败。

如上所述的任何情况都需要特定的例外情况,例如<::的这种情况,我们可以在以下代码中看到一个示例:

template<typename T> class SomeClass;
class Class;

SomeClass<::Class>* cls;
<{3>}中涵盖的

,例外情况在最大蒙克规则正上方的子弹中列出:

  

否则,如果接下来的三个字符是&lt; ::并且后续字符既不是:也不是&gt;,则&lt;   被视为预处理器令牌本身而不是备用令牌的第一个字符&lt;:。

当然还有您在问题中引用的非嵌套>

请注意,我们可以看到>=是来自2.13 [lex.operators] 的预处理器令牌,其中包含:

  

C ++程序的词汇表示包括许多用于的预处理标记   预处理器的语法或转换为运算符和标点符号的标记:

并在列表中包含>=

&gt;&gt;修复

我们可以从提案中看到修正了>>案例:this question,其中(强调我的):

  

自从引入尖括号以来,C ++程序员就已经有了   被连续两个直角括号的事实感到惊讶   必须用空格分隔:

#include <vector>
typedef std::vector<std::vector<int> > Table;  // OK
typedef std::vector<std::vector<bool>> Flags;  // Error
     

问题是“最大限度”的“强烈”直接后果   原则以及&gt;&gt;的事实是C ++中的有效标记(右移)。

     

这个问题很小,但是持续存在,令人讨厌,有点儿   令人尴尬的问题。如果成本合理,那么似乎   值得消除意外。

     

本文档的目的是解释允许&gt;&gt;的方法。成为   作为两个闭合角括号,以及讨论   产生的问题。提出了一个具体的选择以及措辞   这将在当前的工作文件中实施该提案。

同时指出>=案例:

  

值得注意的是,&gt;&gt; =也可能出现问题   和&gt; =令牌。例如

void func(List<B>= default_val1);
void func(List<List<B>>= default_val2);
     

这两种形式目前都是不正确的。可能需要   也解决了这个问题,但本文并未提议这样做。

请注意,此更改N1757: Right Angle Brackets