Reputation: 990
I have a following template class:
template<int size, typename Type>
class Matrix {
public:
Matrix();
...
Type operator ()(int row, int column) {...}
private:
std::array<Type, size*size> _array;
}
And I want to overload equal to
comparison operator to compare Matrix
objects:
template <int size, typename LeftType, typename RightType>
bool operator ==(const Matrix<size, LeftType> & left, const Matrix<size, RightType> & right) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
...
}
}
}
The problem is that comparison of integer types and real types is quite different:
real case
:
template <int size, typename LeftType, typename RightType>
bool operator ==(const Matrix<size, LeftType> & left, const Matrix<size, RightType> & right) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
if (qFuzzyIsNull(left(i, j)) || qFuzzyIsNull(right(i, j))) {
if (!qFuzzyCompare(left(i, j) + 1, right(i, j) + 1)) {
return false;
}
} else {
if (!qFuzzyCompare(left(i, j), right(i, j))) {
return false;
}
}
}
}
return true;
}
(I'm using Qt's qFuzzyCompare and qFuzzyIsNull)
integer case
:
template <int size, typename LeftType, typename RightType>
bool operator ==(const Matrix<size, LeftType> & left, const Matrix<size, RightType> & right) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
if (left(i, j) != right(i, j)) {
return false;
}
}
}
return true;
}
How to enable integer case
if both LeftType
and RightType
integer and enable real case
if at least one LeftType
or RightType
is real?
Upvotes: 0
Views: 997
Reputation: 3902
How about this:
template <int size, typename LeftType, typename RightType>
bool operator ==(const Matrix<size, LeftType> & left, const Matrix<size, RightType> & right) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
if (not is_equal(left(i,j), right(i,j)) {
return false;
}
}
}
return true;
}
and then you either define several overloaded variants of is_equal or make is_equal a template and define it's specializations, like
template<class T>
bool is_equal(const T a, const T b);
template<>
bool is_equal<int>(const int a, const int b){
return a == b;
}
template<>
bool is_equal<real>(const real a, const real b){
...
}
(or as a template over two types if that can happen)
You could, of course, specialize the operator itself, but that means that you have to write the same code all over again without any chance that you will reuse it. Meanwhile, is_equal could become some common tool in your program.
(note: is_equal is a somewhat basic name, so it should be in a namespace, obviously)
Upvotes: 1