How to increase the accuracy of templates in C ++ depending on the type of template?

I have a template math function that takes two values, does some math for them, and returns a value of the same type.

template <typename T> T math_function(T a, T b) { LongT x = MATH_OP1(a,b); return MATH_OP2(x,a); } 

I want to store intermediate values ​​(in x) in a type that is basically a long version of T (above, called LongT). So, if T is a float, I want x to be double; and if T is int, I want x to be a long int.

Is there any way to do this? I tried enable_if , but it seems to me that I really need enable_if_else .

I would prefer the compiler to understand what to use for LongT on its own. I would prefer not to specify it when calling the function.

+4
source share
5 answers

You can define a type mapping that gives the type you need:

 template <typename T> struct long_type; template <> struct long_type<int> { typedef long type; }; template <> struct long_type<float> { typedef double type; }; 

And then use this metafung:

 template <typename T> T math_function(T a, T b) { typename long_type<T>::type x = MATH_OP1(a,b); return static_cast<T>(MATH_OP2(x,a)); } 

With this particular implementation, your template will not be able to compile for any type, except for those for which you have provided the long_type attribute. You might want to provide a generic version that will simply be mapped to itself, so if the input long long int is what is used (assuming your architecture is no longer of type).

+5
source

Assuming you don't need to handle T=long , for example, just create traits for int and float :

 template <typename T> struct LongT; template <> struct LongT<int> { typedef long value_type; }; template <> struct LongT<float> { typedef double value_type; }; template <typename T> T math_function(T a, T b) { typename LongT<T>::value_type x = MATH_OP1(a,b); return MATH_OP2(x,a); } 
+5
source

In C ++ 11, you can use the auto keyword to get the type MATH_OP . It is safe and handled by the compiler.

 auto x = MATH_OP1(a,b); 
+3
source
 template<typename T> struct LongT {typedef T type;} template<> struct LongT<int8_t> {typedef int16_t type;} template<> struct LongT<int16_t> {typedef int32_t type;} template<> struct LongT<int32_t> {typedef int64_t type;} template<> struct LongT<int64_t> {typedef intmax_t type;} // same for unsigned ... template<> struct LongT<float> {typedef double type;} // template<> struct LongT<double> {typedef long double type;} 

Used like this:

 typename LongT<T>::type x; 
+1
source

You can write your own specializations of your own structure or use something like

 #include <type_traits> template<typename T> void func(const T& f, const T& s) { typename std::conditional < std::is_same<T, float>::value, double, typename std::conditional < std::is_same<T, int>::value, long, void >::type >::type X(f + s); (void)X; } int main() { func(1, 1); func(1.0f, 1.0f); func(1.0, 1.0); } 

http://liveworkspace.org/code/8f75236b880a3fe210a8751e485a47ed

But write your own specializations, as suppose David or Mark are pretty smart.

0
source

All Articles