Использование std::enable_if во избежание неоднозначной перегрузки шаблонных бинарных операторов

Я хочу использовать std::enable_if, чтобы избежать неоднозначной перегрузки operator*(T,U) (или переопределений) между MyClass*otherT vs otherT*MyClass vs MyClassT*MyClassT.

Допустим, объявление MyClass:

template <typename T> class MyClassT { ... };

Тогда в глобальном масштабе:

template <typename T, typename U>
MyClassT<T> operator*(const MyClassT<T>& t, const MyClassT<U>& u)
{
    //...
}

template <typename T, typename U, std::enable_if_t<!std::is_same_v<MyClassT<T>, U>,bool> = true >
MyClassT<T> operator*(const MyClassT<T>& t, const U& u)
{
    //...
}

template <typename T, typename U, std::enable_if_t<!std::is_same_v<MyClassT<U>, T>,bool> = true >
MyClassT<U> operator*(const T& t, const MyClassT<U>& u)
{
    //...
}

Но этот код все еще не может найти для него перегруженный оператор:

MyClassT<double> a;
double b;
MyClassT<double> c = a * b; 

Мне нужна помощь, что случилось?

Всегда публикуйте полную ошибку вместе с вопросом с минимально воспроизводимым примером

user12002570 27.06.2024 13:56
... недействителен в С++. Публикуйте только реальный код. Я видел, как люди (спрашивающие) меняли свой вопрос после публикации ответа, говоря, что это всего лишь пример, а не настоящий код. Поэтому всегда публикуйте реальный код. Это редактирование делает недействительными уже опубликованные ответы.
user12002570 27.06.2024 13:57

@user12002570 user12002570 это всего лишь пример фрагмента кода, и тело функции не имеет отношения к вопросу.

uray 27.06.2024 14:04

@wohlstad второй должен содержать T=double, а U=doubleMyClassT<double> не то же самое, что `double` , поэтому объявление будет действительным (обратите внимание !std::is_same_v

uray 27.06.2024 14:06

@uray Вам вообще не нужно использовать Enable_if. Смотрите мой ответ ниже.

user12002570 27.06.2024 14:07

Добавьте больше примеров к своему вопросу. Кажется, вы меняете требования к вопросу после того, как уже опубликованы два ответа.

Alan 27.06.2024 14:19

на минутку, я вернусь к этому, ответ ниже - работа над тестом, но мой случай (с полным кодом) не работает, я проверю, есть ли что-то, что я пропустил в упрощенном коде, что не представляет вопрос

uray 27.06.2024 14:27

окей, ребята, извините, кажется, у меня проблема с AnotherMyClassT<T>, которая также перегружает оператор* между AnotherMyClassT<T> и U, поэтому каким-то образом между MyClassT и AnotherMyClassT возникает множественная/конфликтующая перегрузка.

uray 27.06.2024 14:37

@uray, ты прав насчет второй перегрузки. Это означает, что ваш опубликованный код на самом деле не имеет проблем (демо в комментарии под принятым ответом показывает, что он компилируется)

wohlstad 27.06.2024 14:52

@uray Возможно, вы захотите отредактировать свой вопрос, сказав, что хотите улучшить свой вопрос, сделав его более читабельным, поскольку опубликованный вами код уже работает.

user12002570 28.06.2024 04:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
10
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Здесь не нужно использовать enable_if и аргумент по умолчанию, как показано ниже.

template <typename T, typename U >
MyClassT<T> operator*(const MyClassT<T>& t, const U& u)
{
    //...
    return {};
}

template <typename T, typename U >
MyClassT<U> operator*(const T& t, const MyClassT<U>& u)
{
    //...
    return {};
} 
MyClassT<double> a;
double b;
MyClassT<double> c = a * b;  //works now
MyClassT<double> k = b * a; //works  

Рабочая демо

попробуйте с int b

uray 27.06.2024 14:09

@uray, вот почему мы просим минимально воспроизводимый пример вы должны показать весь код, с которым вы хотите работать, иначе люди будут делать предположения

Alan Birtles 27.06.2024 14:13

@user12002570 user12002570 после комментариев под вопросом: можете ли вы объяснить, почему вторая перегрузка (с T=double и U=double) не соответствует случаю c = a * b в коде ОП? (несмотря на использование !std::is_same_v<MyClassT<T>, U>).

wohlstad 27.06.2024 14:36

@wohlstad На самом деле это работает. Смотрите демо

user12002570 27.06.2024 14:46

Ага, понятно. Значит, весь вопрос на самом деле был неправильным, не так ли? (Я имею в виду, что исходный код действительно работал)

wohlstad 27.06.2024 14:51

@wohlstad Ага, пропустили написать bool. Но все же сфины им здесь не нужны.

user12002570 27.06.2024 14:52

;@wohlstad Да, изначально он не компилировался.

user12002570 27.06.2024 15:13

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

Законно ли инициализировать массив через функтор, который принимает сам массив в качестве параметра по ссылке?
Как эффективно использовать std::variant для обработки ошибок в C++?
Является ли доступ к глобальной «статической» переменной из одного TU гарантированно безопасным?
«Процесс завершен с кодом завершения -1073740791 (0xC0000409)» при использовании вектора будущего
Как исправить «Указанный тип не соответствует требованиям Cpp17MoveInsertable»?
Возврат необязательного параметра из шаблонной функции преобразования
Карта C++: как получить ключ, который использовался для добавления элемента в std::map?
Автоматически ли C++ понижает уровень, чтобы найти нужную виртуальную функцию?
Достаточно ли предварительного объявления std::list, чтобы проверить, является ли тип T std::list?
Специализация шаблона вне встроенного пространства имен функции, определенной внутри встроенного пространства имен