为什么在“A< 0> = 0”中的模板标识符没有空间编译,因为更大或等于 - 运算符“> =”? [英] Why does the template-id in "A<0>=0" not compile without space because of the greater-or-equal-than operator ">="?

查看:147
本文介绍了为什么在“A< 0> = 0”中的模板标识符没有空间编译,因为更大或等于 - 运算符“> =”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  template< int> 
using A = int;

void f(A< 0 = 0); //尝试用默认参数声明函数f接受int,
// 0

//按预期工作:
// void f(A< 0> 0);

这不会编译 GCC 4.9.2或Clang 3.5 - 更不用说ICC或VC ++。显然,> = 位被解析为大于或等于 - 运算符。但是,这似乎不正确的关于[temp.names] / 3:


在名称查找(3.4)后发现名称是 b的重载函数,其任何成员是一个函数模板,如果
后面跟着一个 code>始终作为
a 模板参数列表的分隔符,而不是作为小于运算符。
解析模板参数列表时,第一个非嵌套的
> 138 作为结束分隔符
,而不是
大于运算符。 [..] [示例:

 模板< int i& class X {/ * ... * /}; 

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

- 结束示例]



138)包含 type-id > dynamic_cast
static_cast reinterpret_cast const_cast 或包含
的后续 template-id
模板参数


我缺少某些东西,或者这是一个编译器错误?

解决方案

这是最大压缩原则,其具有词法分析器接收尽可能多的字符以形成有效的令牌。这在草案C ++标准部分 2.5 [lex.pptoken] 中说明:



< blockquote>

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


任何情况,例如上面提到的情况都需要一个特定的异常,例如< :: ,我们可以在以下代码中看到一个示例:

  template< typename T&类SomeClass; 
class Class;

SomeClass< :: Class> * cls;

这个问题,异常被列在刚好在最大munch规则上方的项目符号中:


否则,如果接下来的三个字符是< ::,并且后续字符既不是:也不是>
被视为预处理器令牌,而不是作为替代令牌<:。


的第一个字符当然是在你的问题中引用的非嵌套>



注意,我们可以看到> = / code> [lex.operators] 其中:


C ++程序的词汇表示法包括预处理器的语法中使用的多个预处理标记,或者转换为操作符和标点符号的标记:




> =



/ p>

我们可以从提案中看到修复>> case: N1757:直角括号说明(强调我的):


自从引入尖括号以来,C ++程序员已经对
感到惊讶,因为两个连续的右尖括号
必须用空格分隔:

  #include< vector> 
typedef std :: vector< std :: vector< int> >表; // OK
typedef std :: vector< std :: vector< bool>>标志; //错误

问题是最大munch的一个 $ b原则以及>>是C ++中的有效标记(右移)。



这个问题是次要的,但是坚持,恼人,和有点
尴尬问题。如果成本是合理的,因此似乎
值得消除惊喜。



本文档的目的是解释允许>>为
处理为两个闭合尖括号,以及讨论
导致的问题。提出了一个具体的选项以及将在当前工作文件中实施该提案的措辞


> = case:


这也值得注意的问题可以也会出现在>> =
和> = tokens
。例如

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

这两种表单目前都是错误的。


注意,这个更改违反了与C ++ 03的向后兼容性


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);

This neither compiles on GCC 4.9.2 nor Clang 3.5 - let alone ICC or VC++. Apparently the >= bit is parsed as a greater-or-equal-than operator. However, this seems to be incorrect regarding [temp.names]/3:

After name lookup (3.4) finds that a name is a template-name or that an operator-function-id or a literal- operator-id refers to a set of overloaded functions any member of which is a function template, if this is followed by a <, the < is always taken as the delimiter of a template-argument-list and never as the less-than operator. When parsing a template-argument-list, the first non-nested >138 is taken as the ending delimiter rather than a greater-than operator. [..] [ Example:

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

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

— end example ]

138) A > that encloses the type-id of a dynamic_cast, static_cast, reinterpret_cast or const_cast, or which encloses the template-arguments of a subsequent template-id, is considered nested for the purpose of this description.

Am I missing something or is this a compiler bug?

解决方案

This an effect of the maximal munch principle, which has the lexical analyzer take as many characters as possible to form a valid token. This is covered in draft C++ standard section 2.5 [lex.pptoken] which says:

Otherwise, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token, even if that would cause further lexical analysis to fail.

Any cases such as the one you cite above need a specific exception carved out such as this case for <::, we can see an example in the following code:

template<typename T> class SomeClass;
class Class;

SomeClass<::Class>* cls;

which is covered in this question, the exception is listed in the bullet just above the maximal munch rule:

Otherwise, if the next three characters are <:: and the subsequent character is neither : nor >, the < is treated as a preprocessor token by itself and not as the first character of the alternative token <:.

and of course the non-nested > which you cite in your question.

Note we can see that >= is a preprocessor token from section 2.13 [lex.operators] which says:

The lexical representation of C++ programs includes a number of preprocessing tokens which are used in the syntax of the preprocessor or are converted into tokens for operators and punctuators:

and includes >= in the list.

The >> fix

We can see from the proposal that fixed the >> case: N1757: Right Angle Brackets which says (emphasis mine):

Ever since the introduction of angle brackets, C++ programmers have been surprised by the fact that two consecutive right angle brackets must be separated by whitespace:

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

The problem is an immediate consequence of the the "maximum munch" principle and the fact that >> is a valid token (right shift) in C++.

This issue is a minor, but persisting, annoying, and somewhat embarrassing problem. If the cost is reasonable, it seems therefore worthwhile to eliminate the surprise.

The purpose of this document is to explain ways to allow >> to be treated as two closing angle brackets, as well as to discuss the resulting issues. A specific option is proposed along with wording that would implement the proposal in the current working paper.

Also points out the >= case:

It is also worth noting that the problem can also occur with the >>= and >= tokens. For example

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

Both of these forms are currently ill-formed. It may be desirable to also address this issue, but this paper does not propose to do so.

Note, this change broke backward compatibility with C++03.

这篇关于为什么在“A&lt; 0&gt; = 0”中的模板标识符没有空间编译,因为更大或等于 - 运算符“&gt; =”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆