Allocating an integer from floating point types in a pattern

I would like to perform similar but not identical calculations for several integer types (16, 32, 64 bits) and floating point types (float, double, long double). Most of the code is identical, but some parts must be executed differently for int and float. For example, an ints comparison can be done using a == b, while a float comparison should be done using abs (ab)

One way to do this is to isolate parts of the code that differ between int and float from small functions and specialize the template for each type. However, I would prefer not to copy the same code for each of the integer types and a different code for each of the float types. Thus, the question arises: is it possible to immediately specialize a template function for several types? 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;
}
+4
source share
3 answers

With C ++ 11, signs can be used. See the std::enable_ifdocumentation . In your case, it may look like this:

Function 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;
}
+14
source

Yes, you can use SFINAE in combination with metafiles 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();
}
+3

You can specialize in <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);
};
+2
source

All Articles