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_cast
,reinterpret_cast
或const_cast
,或附带的{{1}} 该 后续 template-id 的 template-argument 被认为是为了本说明而嵌套的。
我错过了什么或者这是编译错误吗?
答案 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。