Заставить С++ автоматически преобразовывать in в double

Когда у меня есть числовой тип, который определяет operator< для double, но не для int, сравнение с литералами int не работает. Это проблема, так как части стандартной библиотеки, т. е. std::complex, содержат литералы int.

Могу ли я заставить компилятор обрабатывать литералы int как двойные при использовании типа?

Упрощенный пример:

// the defined operator
template<typename T>
bool operator<(const Type<T> &lhs, const T &rhs);

complex<Type<T>> complex_number;
1.0 / complex_number; // this fails

Сбой происходит внутри метода _Div std::complex в

template<class _Other> inline
void _Div(const complex<_Other>& _Right)
    // ...
    else if ((_Rightimag < 0 ? -_Rightimag : +_Rightimag)

что вызывает ошибку:

error C2678: binary '<': no operator found which takes a left-hand operand of type 'Type<T>' (or there is no acceptable conversion)
(...)
complex(665): note: while trying to match the argument list '(Type<T>, int)'
      [
          T=double
      ]

Я думаю, что код в std::complex должен быть _Rightimag < static_cast<_Other>(0) для работы со всеми числовыми типами, но мне приходится работать с тем, что предоставляет stdlib.

Поскольку другой тип также из библиотеки, я ищу способ добавить неявное преобразование в свой код.


Для фактического кода: я использую ceres, который позволяет вам определять функторы с шаблонным скалярным типом для автодифференциации. Скаляр оценивается и как T, и как Jet<T, N>.

Ceres определяет operator<(const Jet<T, N>&, const T&), что позволяет для jet < 0.0, но не для jet < 0.

В моем коде я могу обойти проблему, используя удвоения или явно приводя целые числа к типу шаблона T, но когда я пытаюсь работать с complex<T>, у меня возникают проблемы с методами, которые сравниваются с целочисленными литералами, такими как метод _Div выше.


person allo    schedule 10.09.2018    source источник
comment
Вы говорите, что определили operator< для double, но на самом деле вы определили тот, который принимает произвольный тип T. Корень проблемы в том, что есть два параметра, которые позволяют компилятору вывести T, и когда они расходятся во мнениях относительно того, каким должен быть T, возникает неоднозначность. Есть способы обойти это (вы помещаете один из T в невыведенный контекст), но не похоже, что у вас есть контроль над объявлением operator<. Так что в основном это плохой дизайн со стороны авторов той библиотеки, которую вы используете.   -  person Igor Tandetnik    schedule 10.09.2018
comment
У меня нет контроля над методами экземпляра библиотеки, и я не уверен, что могу определить оператор преобразования вне класса, который затем используется такими классами, как std::complex.   -  person allo    schedule 10.09.2018
comment
Ceres следует определить < как дружественного оператора ADL, а не как оператора свободного шаблона. Это решило бы вашу проблему. friend bool operator op(const Jet& f, const T& s) { return f.a op s; } и т. д.   -  person Yakk - Adam Nevraumont    schedule 10.09.2018


Ответы (2)


Шаблон std::complex не требуется для работы с общими типами. Стандарт говорит [complex.numbers]/2:

Эффект создания экземпляра шаблона complex для любого типа, кроме float, double или long double, не указан.

Если вам нужно обобщить любой другой числовой тип до сложного типа, вы должны использовать какую-то другую библиотеку или реализовать свою собственную.

person aschepler    schedule 10.09.2018
comment
Это звучит правдоподобно, поэтому мне, вероятно, нужно реализовать собственный сложный тип с функциями, которые мне действительно нужны, или использовать две переменные и определить функции для необходимых операций. - person allo; 10.09.2018
comment
Я написал собственный сложный тип с необходимыми мне базовыми операциями, и он у меня работает. По-прежнему кажется, что stdlib должна быть в состоянии предоставить, когда есть шаблонный тип. С другой стороны, ceres везде требуется много явных приведений к своему скалярному типу, с которым тоже не очень приятно работать. - person allo; 11.09.2018

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

person Tim Randall    schedule 10.09.2018
comment
Могу ли я определить это в своем коде без исправления библиотеки? Это открытый исходный код, но я хотел бы сослаться на немодифицированную библиотеку, если это возможно. - person allo; 10.09.2018
comment
У меня сложилось впечатление, что все задействованные типы предоставляются внешними библиотеками, и было бы нецелесообразно изменять их (например, добавляя конструктор). - person François Andrieux; 10.09.2018