Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does gcc reject `new v < new v` when `v` is not a template?

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)


Addendum

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.


Note:

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.

like image 814
rici Avatar asked Jan 22 '17 00:01

rici


Video Answer


1 Answers

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)

like image 78
rici Avatar answered Nov 15 '22 12:11

rici