Проблема более или менее классическая.Разрешение перегрузки начинается с создания списка возможных функций;в этом случае функции с именем operator*
.Для этого он добавляет все operator*
функции, которые находятся в области видимости, в список и пытается создать экземпляр всех шаблонов функций, применяя дедукцию типа;если вывод типа завершается успешно, он добавляет экземпляр шаблона в список.(Шаблон функции - это , а не функция. Создание экземпляра шаблона функции - это функция.)
Правила для вывода типа шаблона отличаются от правил, используемых при разрешении перегрузки.В частности, рассматривается только очень маленький набор преобразований.Определяемые пользователем операторы преобразования не рассматриваются.В результате в m1 * m2
вычет типа для operator*
завершается неудачно (поскольку для этого потребуется преобразование, которое не рассматривается).Таким образом, создание экземпляра шаблона функции не добавляется в список, и нет других operator*
.
В более общем смысле: вы operator T2()
не допустили бы вычитание типа, даже если бы это было разрешено;существует бесконечное количество конверсий, которые соответствуют operator*
.На самом деле я подозреваю, что вы сделали это слишком общим;что вы хотите operator Matrix<M, N, T2>()
.(Не то, чтобы это помогло, но есть ситуации, в которых это может устранить неоднозначность.)
Вы могли бы заставить это работать, определив:
template<size_t P, tyepname OtherT>
Matrix<M, P, T> operator*( Matrix<N, P, T> const& rhs ) const;
, а затем выполнивконвертация внутри оператора *.(Я не пробовал и не уверен, но я думаю, что ваш существующий operator*
следует считать «более специализированным», и, таким образом, его следует выбирать, когда вычитание типа будет успешным для обоих.)
Сказав этоЯ думаю, то, как ты это делаешь, - неправильный подход.Вы действительно хотите, чтобы типы возврата m1 * m2
и m2 * m1
были разными.Для начала, я бы потребовал, чтобы клиентский код сделал преобразование явным (что имеет место в вашем текущем коде);если вы хотите поддерживать неявные преобразования, я думаю, вам нужно сделать operator*
глобальным, использовать какое-то простое метапрограммирование для определения правильного типа возвращаемого значения (т. е. заданных матриц long
и unsigned
,вы можете захотеть иметь тип возвращаемого значения unsigned long
, поскольку это то, что арифметика смешанного типа с этими типами дает в противном случае), преобразовать обе стороны в целевой тип и выполнить арифметику для него.Много работы для того, что, вероятно, не очень важная или полезная функция.(Просто мое мнение, конечно. Если ваши клиенты действительно хотят смешанную арифметику и готовы за нее платить ...)