Почему оператор, не являющийся членом, и шаблонный оператор синтаксически корректен, но не работает в C++

Я вижу, что синтаксически правильно следующее:

#include <iostream>
using namespace std;
template<class T> bool operator<= (const T& left, const T& right)
{
  cout<<"overloaded"<<endl;
  return left<=right;
}


int main()
{
    cout<<(10<=5)<<endl;
    return 0;
}

Но кажется, что его никогда не вызывают.

Здесь оно называется просто отлично: godbolt.org/z/b9r3Phcv7

Yksisarvinen 03.05.2024 20:04

Я указал, как звонить оператору

Discipulos 03.05.2024 20:07

Почему ... вместо того, что можно скомпилировать и протестировать и продемонстрировать проблему?

Retired Ninja 03.05.2024 20:07

Примечание: не делайте этого в рабочем коде (вы также перегружаете операторы для типов встроенных и стандартных библиотек). Это может привести к неожиданным результатам (например, большая часть кода перестанет работать правильно).

Pepijn Kramer 03.05.2024 20:08

Да, я просто хотел бы знать, что здесь происходит

Discipulos 03.05.2024 20:08

В общем, вы можете перегружать операторы только в том случае, если у вас есть хотя бы один из типов операндов. Следовательно, вы не можете изменить поведение операторов для встроенных типов.

HolyBlackCat 03.05.2024 20:09

«Да, я просто хотел бы знать, что здесь происходит». Все просто: 10<=5 вызывает встроенный оператор bool по умолчанию, проверяя, меньше ли 10 или равно 5, он не вызывает ваш новый оператор. Как сказал HolyBlackCat, вы не можете изменить поведение операторов для встроенных модулей. В лучшем случае вы можете обернуть их в структуру или класс шаблона и использовать этот новый тип с другим поведением (см. пример Иксисарвинена).

TheNomad 03.05.2024 20:17

Вы не можете перегружать предопределенные операторы для предопределенных типов.

armagedescu 03.05.2024 20:21

Примечание: когда эта функция действительно вызывается, return left<=right; будет вызывать одну и ту же функцию рекурсивно, навсегда (или до тех пор, пока программа не выйдет из строя).

Pete Becker 03.05.2024 20:33

Тот факт, что что-то синтаксически правильно, не означает, что оно делает то, что, по вашему мнению, оно делает (или должно делать).

Jesper Juhl 04.05.2024 02:41
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
12
105
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для вызова перегруженных операторов хотя бы один операнд должен иметь тип класса или перечисления:

Если ни один операнд оператора в выражении не имеет типа, являющегося классом или перечислением, оператор считается встроенным и интерпретируется в соответствии с [expr.compound].

- [over.match.oper] п1

Ваш operator<= действителен и будет вызван, если один из операндов был, скажем, классового типа, но в 10<=5 оба операнда имеют int, т. е. фундаментального типа.

Также обратите внимание, что return left<=right; приведет к бесконечной рекурсии (почти во всех случаях), поскольку он снова вызовет перегруженный оператор <=.

Более того, крайне необычно перегружать операторы таким образом, чтобы они вызывались для типов стандартной библиотеки (или пытались сделать это для фундаментальных типов). См. также Можно ли перегружать оператор+ для типов стандартной библиотеки и встроенного типа?. Вам следует придерживаться перегрузки операторов только для ваших собственных типов, например. сделав их скрытыми friend или функциями-членами или правильно ограничив их.

Следуя комментарию Юксисарвинена под вопросом, это не приведет к бесконечной рекурсии.

Discipulos 04.05.2024 21:04

@Discipulos, потому что функция Юксисарвинена заканчивается на return false;. Ваша функция заканчивается на return left<=right;, что приводит к бесконечной рекурсии: godbolt.org/z/1jGY9h9hE

Jan Schultke 04.05.2024 21:08

Другие вопросы по теме