c++ - 为什么 "A<0>=0"中的模板 ID 由于大于或等于运算符 ">="而不能在没有空格的情况下编译?

标签 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++。显然 >= bit 被解析为大于或等于运算符。但是,对于 [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.

是我遗漏了什么还是这是一个编译器错误?

最佳答案

这是 maximal munch principle 的效果,它使词法分析器采用尽可能多的字符来形成有效的标记。这在草案 C++ 标准部分 2.5 中有介绍。 [lex.pptoken] 上面写着:

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.

您在上面引用的任何情况都需要一个特定的异常(exception)情况,例如 <:: 的情况。 ,我们可以在下面的代码中看到一个例子:

template<typename T> class SomeClass;
class Class;

SomeClass<::Class>* cls;

this question 中有介绍,异常(exception)情况列在最大咀嚼规则上方的项目符号中:

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 <:.

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

请注意,我们可以看到 >=是来自 2.13 部分的预处理器标记[lex.operators] 说:

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:

包括>=在列表中。

>>修复

我们可以从修复 >> 的提案中看到案例:N1757: Right Angle Brackets上面写着(强调我的):

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.

还指出>=案例:

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.

请注意,此更改 broke backward compatibility with C++03 .

关于c++ - 为什么 "A<0>=0"中的模板 ID 由于大于或等于运算符 ">="而不能在没有空格的情况下编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28354108/

相关文章:

c++ - CMake 冲突的头文件

c++ - 在另一个函数中调用随机函数

c++ - 特定类型的部分模板特化,C++

c++ - 如何创建自定义随机分布函数?

c++ - 有没有办法使用对象及其非空参数列表调用运算符来生成 std​​::thread ?

c# - 在 C# 中使用 webkit 库的问题

c++ - 如何在 C++ 中禁用 CComboBox?

c++ - 可变参数模板的模板特化

c++ - 依赖类型 : Template argument deduction failed

c++ - 如果自定义分配器中不存在重新绑定(bind),std::allocator_traits 是否定义 rebind_alloc?