简单的测试用例:
#include <iostream>
struct v {};
int main() {
std::cout << __VERSION__ << '\n' << (new v < new v) << '\n';
}
我知道比较指针有一个未指定的结果,但这里没有相关性(类似的例子可以用更多的击键产生,就像后面的coliru片段一样)。
我方便的C ++标准在§14.2第3段中说:
名称查找后发现名称是模板名称或 operator-function-id 或 literal-operator-id 是指一组重载函数,其中任何成员都是函数模板,如果后跟&lt; ,则&lt; 始终作为分隔符 template-argument-list ,而不是小于运算符。
由于v
既不是模板名也不是函数id,我不明白为什么这应该适用。显然,clang:
4.2.1 Compatible Clang 3.8.0 (tags/RELEASE_380/final 263969)
1
然而,gcc(6.3.0)抱怨:
main.cpp: In function 'int main()':
main.cpp:4:46: error: 'v' is not a template
std::cout << __VERSION__ << '\n' << (new v < new v) << '\n';
^
我(和铿锵)在这里遗漏了什么吗?
使用减号运算符而不是小于gcc的版本(无编译错误)
Gcc没有相同的功能问题;使用template functions,它坚持&lt; 必须是模板参数分隔符,而不是non-template functions。这增加了它是一个错误的论点,因此我将其归档为Bug 79192。
如果有人好奇的话,在我试图回答this question的时候出现了这个问题,提问者正在为一个模糊的C ++语言写一个语法,并且偶然发现了上述歧义。我想解释一下C ++使用的解决方案,但是两个编译器之间的差异使得它变得困难。
答案 0 :(得分:5)
这是一个错误,或者至少错误报告被GCC维护者接受了。
在评论中,Johannes Schaub-litb指出拒绝此构造的代码位于cp/parser.c
的第16781行:
/* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user thought
that the type was a template. */
cp_parser_check_for_invalid_template_id (parser, type, none_type,
token->location);
并且注释不正确,因为检查还拒绝其他有效程序,例如
struct A {
operator A();
};
void operator<(A (A::*)(), A);
int main() {
&A::operator A < A();
}