Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Distinguishing integer from floating point types in a template

Tags:

c++

templates

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;
}
like image 266
Michael Avatar asked Nov 14 '13 18:11

Michael


2 Answers

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;
}
like image 171
Erbureth Avatar answered Nov 15 '22 06:11

Erbureth


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();
}
like image 29
sbabbi Avatar answered Nov 15 '22 06:11

sbabbi