Is there any way to double the precision returned by multiply (to avoid overflow)?
template<class T> class MyClass {
T multiply (T a, T b) { return a * b; }
}
Something like:
long T multiply (T a, T b) { return a * b; }
So that whether 'int', 'long', or 'double' was given, a 'long int', 'long long', or 'long double' would be returned from multiply.
This is a general question. I'm working around it by using a double internally. But my question is whether there is any mechanism to promote a type to its "long" variant in C++?
@Andy has the right answer, which works quite well. But for those who want a compile-time error if MyClass is instantiated with a type for which there is no 'long' value, I've combined it with @SteveJessop's excellent comment to give the following solution:
// --- Machinery to support double-precision 'T' to avoid overflow in method 'multiply' ---
// Note: uncomment typedef if don't want compile-time errors
// when no "long" type exists
// ----
template<typename T>
struct add_long { /*typedef T type;*/ };
template<> struct add_long<int8_t> { typedef int16_t type; };
template<> struct add_long<int16_t> { typedef int32_t type; };
template<> struct add_long<int32_t> { typedef int64_t type; };
template<> struct add_long<uint8_t> { typedef uint16_t type; };
template<> struct add_long<uint16_t> { typedef uint32_t type; };
template<> struct add_long<uint32_t> { typedef uint64_t type; };
template<> struct add_long<float> { typedef double type; };
template<> struct add_long<double> { typedef long double type; };
Example usage of 'longT':
template<class T> class MyClass
{
// Note: a compiler error on the next line means that
// class T has no double-precision type defined above.
typedef typename add_long<T>::type longT;
public:
longT multiply (T a, T b) { return longT(a) * b; }
}
Example Usage of MyClass:
MyClass<float> my;
printf("result = %lf\n", my.multiply(3.4e38, 3.4e38));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With