For example, std::complex (which "circumvents" the problem by
disallowing UDT value types) defines
template<class T> complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs);
However, even for a simple value type (e.g. integers - N.B.
not int) this is not correct since integer/integer ->
rational so this should really be
template<class T> complex<rational> operator*(const complex<integer>& lhs, const complex<integer>& rhs);
In general, anywhere that
template<class T> something<T> operator blah(const something<T>& lhs, const something<T>& rhs);
appears should look like (pseudocode)
template<class T> something<typeof(T blah T)> operator*(const something<T>& lhs, const something<T>& rhs);
instead. This requires a bit more care, but I think it is
demonstrably the right thing to do and should probably be an
expectation in Boost libraries. For example, I know that
Boost.Quaternions, Boost.Octonions, and Boost.uBlas do not do
the right thing in this context. It would also probably make
sense to provide a Boost.Complex that allows UDTs and handles
them correctly. It sounds like Boost.Geometry also does not
correctly handle basic mathematical operators.