Reputation: 5939
I'd like to perform similar, but not identical computations for several integer types (16, 32, 64 bits) and floating point types (float, double, long double). Most of the code is identical, but some portions need to be done differently for ints and floats. For example, comparing ints can be done with a==b, while comparing floats should be done with abs(a-b)
One way to do that would be to isolate the parts of code that are different between ints and floats into small functions and specialize template for each type. However, I'd rather not to copy-paste identical code for each of the integer types and another code for each of the float types. Thus the question: is it possible to specialize template function for multiple types at once? Something semantically similar to the following if it was legal:
template<>
bool isEqual< short OR long OR long long >( T a, T b ) {
return a == b;
}
template<>
bool isEqual< float OR double OR long double >( T a, T b ) {
return abs( a - b ) < epsilon;
}
Upvotes: 6
Views: 5794
Reputation: 11191
Yes, you can use SFINAE in combination with the metafunctions from <type_traits>
#include<type_traits>
template<class IntegralType>
typename std::enable_if<
std::is_integral<IntegralType>::value,
bool>::type
isEqual(IntegralType a,IntegralType b)
{
return a == b;
}
template<class FloatingType>
typename std::enable_if<
std::is_floating_point<FloatingType>::value,
bool>::type
isEqual(FloatingType a,FloatingType b)
{
return fabs(a-b) < std::numeric_limits<FloatingType>::epsilon();
}
Upvotes: 4
Reputation: 10343
You can specialize on <type_traits>
Then you can group functions based on categories
template<typename T, bool INTEGRAL> class isEqualbyType;
template<typename T>
class isEqualbyType<T, true>
{
public:
static bool cmp( T a, T b ) {
return a == b; }
};
template<typename T>
class isEqualbyType<T, false>
{
public:
static bool cmp( T a, T b ) {
static const double epsilon=1e-50;
return abs( a - b ) < epsilon; }
};
template<typename T>
bool isEqual( T a, T b )
{
return isEqualbyType<T, std::is_integral<T>::value>::cmp(a,b);
};
Upvotes: 2
Reputation: 3423
With C++11 it is possible to use type traits. See std::enable_if
documentation
In your case, it might look like this:
Function parameter specialization:
template<class T>
bool isEqual(T a, T b, typename std::enable_if<std::is_integral<T>::value >::type* = 0)
{
return a == b;
}
template<class T>
bool isEqual(T a, T b, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0)
{
return abs( a - b ) < epsilon;
}
Return type specialization:
template<class T>
typename std::enable_if<std::is_integral<T>::value, bool >::type isEqual(T a, T b)
{
return a == b;
}
template<class T>
typename std::enable_if<std::is_floating_point<T>::value, bool >::type isEqual(T a, T b)
{
return abs( a - b ) < epsilon;
}
Upvotes: 18