c++implicit-conversionceres-solver

Make C++ automatically convert int to double


When I have a numeric type, which defines operator< for double, but not for int, comparision with int literals does not work. This is a problem, as parts of the standard library, i.e. std::complex contain int literals.

Can I make the compiler treat int literals as double when using the type?

Simplified example:

// 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

The failure happens inside the _Div method of std::complex at

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

which causes the error:

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
      ]

I think probably the code in std::complex should be _Rightimag < static_cast<_Other>(0) to work with all numeric types, but I have to work with what the stdlib provides.

As the other type is from a library as well, I am looking for a way to add the implicit conversion to my code.


For the actual code: I am using ceres, which lets you define functors with a templated scalar type for autodifferentiation. The scalar is both evaluated as T and as Jet<T, N>.

Ceres defines operator<(const Jet<T, N>&, const T&), which allows for jet < 0.0 but not for jet < 0.

In my code I can work around the problem by using doubles or explicitely casting integers to the template type T, but when I try to work with complex<T> I get into trouble for the methods which compare against integer literals, like the _Div method above.


Solution

  • The std::complex template is not required to work with general types. The Standard says [complex.numbers]/2:

    The effect of instantiating the template complex for any type other than float, double, or long double is unspecified.

    If you need to generalize any other numeric-like type to a complex-like type, you should be using some different library or implementing your own.