How to change the template method based on whether the type is integral or floating point?

I am working on a Matrix class that accepts both integral (short, int, long) and floating-point types (float, double). I want some methods to be limited only to floating point types (for example, the inversion method), and some methods should have different implementations for floating types and integral types (for example, the == operator). I have an assumption that the correct way is to use boost "enable_if" and "is_integral" / "is_floating_point", but I cannot get it to work.

My implementation is similar to this C ++ pseudo-code:

template <typename T>
class Matrix
{
    ...
    bool operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const;
    bool operator==(Matrix<typename enable_if<is_floating_point<T>::type T> >) const;
    typename enable_if<is_floating_point<T> T> computeInverse() const;
    ...
};
// implementation
bool Matrix<T>::operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const {
  //implementation without precision
}
bool Matrix<T>::operator==(Matrix<typename enable_if<is_integral<T> T >::type >) const {
  //implementation using precision
}
Matrix<typename enable_if<is_floating_point<T> T>::type > Matrix<T>::computeInverse() const {
  //implementation requiring floating points
}

This creates a lot of compilation errors, whereas I think these are the most relevant:

error: no type named ‘typein ‘struct boost::enable_if<boost::is_integral<float>, float>’

and

error: no type named ‘type’ in ‘struct boost::enable_if<boost::is_floating_point<int>, int>’

, , , boost enable_if, ?

, ? , , .

+3
2

Matrix:

template <typename T>
class Matrix
{
    template <bool isInteger> class Discrim;
    //  ...
    bool isEqual( Matrix const& other, Discrim<true> ) const
    {
        //  Integer implementation...
    }

    bool isEqual( Matrix const& other, Discrim<false> ) const
    {
        //  Floating point implementation...
    }

public:
    bool isEqual( Matrix const& other ) const
    {
        return isEqual( other, Discrim<std::numeric_limits<T>::is_integer>() );
    }
};

operator== operator!= Matrix::isEqual, .

: , " ", T - . . ( == ).

+2

@DavidRodriguez ; , . .

, SFINAE :

#include <iostream>
#include <type_traits>

template<class T>
struct Matrix
{
  // ...
};

template<class T>
typename std::enable_if<
    std::is_integral<T>::value, bool
  >::type
operator==( const Matrix<T>&, const Matrix<T>& )
{
  std::cout << "Integer version" << std::endl;
  return true;
}

template<class T>
typename std::enable_if<
    !std::is_integral<T>::value, bool
  >::type
operator==( const Matrix<T>&, const Matrix<T>& )
{
  std::cout << "Floating point version" << std::endl;
  return true;
}

int main()
{
  Matrix<int> m1, m2;
  Matrix<double> m3, m4;

  if( m1 == m2 ) {}

  if( m3 == m4 ) {}
}

, - , , , && std::is_same<T,U> std::enable_if.

+1

All Articles