Подтвердить что ты не робот

Почему gcc отклоняет `new v <new v`, когда` v` не является шаблоном?

Простой тестовый пример:

#include <iostream>
struct v {};
int main() {
    std::cout << __VERSION__ << '\n' << (new v < new v) << '\n';
}

Я знаю, что сравнение указателей имеет неуказанный результат, но это не имеет значения здесь (и аналогичный пример может быть получен с несколькими нажатиями клавиш, как в последующих фрагментах coliru).

Стандарт С++, который я могу вам сказать, в пункте 14.2 раздела:

После поиска имени находит, что имя является именем шаблона или что оператор-функция-идентификатор или идентификатор литерала-оператора относится к набору перегруженных функций, любой из которых является шаблоном функции, если это выполняется по <, < всегда берется как разделитель списка шаблонов-аргументов и никогда не работает как оператор меньшего размера.

Так как v не является ни именем шаблона, ни идентификатором функции, я не понимаю, почему это должно применяться. И ни то, ни другое, по-видимому, 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';
                                              ^

Неужели я (и clang) что-то пропустил?

Версии без неопределенного поведения: clang gcc

Версия с минусом, а не меньше: gcc (нет ошибки компиляции)


Добавление

Gcc не имеет такой же проблемы с функциями; с функции шаблона он настаивает на том, что < должен быть разделителем аргументов шаблона, но не с функции без шаблона. Это добавляет вес аргументам, что это ошибка, поэтому я подал ее как Ошибка 79192.


Примечание:

В случае, если кому-то интересно, это произошло, когда я пытался ответить на этот вопрос, где вопросник писал грамматику для смутно языка С++ и наткнулся на вышеупомянутую двусмысленность. Я хотел объяснить решение, используемое С++, но несоответствие между двумя компиляторами затруднило работу.

4b9b3361

Ответ 1

Это ошибка, или, по крайней мере, отчет об ошибке был принят сторонними разработчиками GCC.

В комментарии Johannes Schaub-litb указал, что код, который отклоняет эту конструкцию, находится в строке 16781 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);

и что комментарий неверен, так как проверка также отклоняет другие допустимые программы, такие как

struct A {
   operator A();  
};

void operator<(A (A::*)(), A);

int main() {
   &A::operator A < A();   
}

(на coliru)