Simple test case:
#include <iostream>
struct v {};
int main() {
std::cout << __VERSION__ << '\n' << (new v < new v) << '\n';
}
I'm aware that comparing the pointers has an unspecified result, but that's not relevant here (and a similar example could be produced with some more keystrokes, as in the later coliru snippets).
The C++ standard I have handy says, in §14.2 paragraph 3:
After name lookup 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.
Since v
is neither a template name nor a function id, I don't see why this should apply. And neither, apparently, does clang:
4.2.1 Compatible Clang 3.8.0 (tags/RELEASE_380/final 263969)
1
However, gcc (6.3.0) complains:
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';
^
Am I (and clang) missing something here?
Versions without unspecified behaviour: clang gcc
Version with minus operator instead of less than: gcc (no compilation error)
Gcc does not have the same problem with functions; with template functions it insists that the < must be a template argument delimiter, but not with non-template functions. That adds weight to the argument that it's a bug, so I filed it as Bug 79192.
In case anyone is curious, this came up while I was trying to answer this question, where the questioner was writing a grammar for a vaguely C++-like language and stumbled on the above ambiguity. I wanted to explain the solution used by C++, but the discrepancy between the two compilers made it difficult.
It's a bug, or at least the bug report was accepted by the GCC maintainers.
In a comment, Johannes Schaub-litb pointed out that the code which rejects this construct is at line 16781 of cp/parser.c
:
/* 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);
and that the comment is incorrect, since the check also rejects other valid programs such as
struct A {
operator A();
};
void operator<(A (A::*)(), A);
int main() {
&A::operator A < A();
}
(on coliru)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With