шаблоны — Сделайте кучу классов C ++ сопоставимыми, избегая повторения в коде

Мне нужно создать группу классов, чтобы экземпляры определенного типа можно было сравнивать друг с другом.

Я подумал о том, чтобы написать метод сравнения, уникальный для каждого класса, а затем добавить следующий код в каждое определение класса, заменив T именем класса, в котором я нахожусь:

bool operator== (const T& L, const T& R)        {return L.compare(R)==0;}
bool operator!= (const T& L, const T& R)      {return L.compare(R)!=0;}
bool operator< (const T& L, const T& R)       {return L.compare(R)<0;}
bool operator<= (const T& L, const T& R)        {return L.compare(R)<=0;}
bool operator> (const T& L, const T& R)       {return L.compare(R)>0;}
bool operator>= (const T& L, const T& R)      {return L.compare(R)>=0;}

Это отчасти повторяется, все же. Есть ли более общий способ сделать это? Думаю, я мог бы написать для этого макрос, параметризовав его на T, но макросы сейчас не очень-то напутаны, не так ли? Я также подумал о наследовании и полиморфизме, и из того, что я читал об этом (я еще не использовал виртуальные классы; я новичок в C ++), кажется, что я буду вводить ненужные накладные расходы времени выполнения, так как я ‘ я не буду нуждаться в единообразном доступе через указатели базового класса. Есть ли лучший способ сделать это, кроме макросов или копирования?

0

Решение

Заголовок <boost/operators.hpp> предоставляет несколько наборов шаблонов классов (в пространстве имен boost). Эти шаблоны определяют операторы в области именного пространства с точки зрения минимального числа фундаментальных операторов, предоставляемых классом.

#include <boost/operators.hpp>
#include <cassert>

struct Integer : boost::totally_ordered<Integer>
{
int value;
Integer(int x) : value(x) {}
};

bool operator<(Integer lhs,Integer rhs)
{
return lhs.value < rhs.value;
}
bool operator==(Integer lhs,Integer rhs)
{
return lhs.value == rhs.value;
}

int main()
{
Integer a(1), b(2), c(1);
// We have defined only operator< and operator==
assert(a < b);
assert(a == c);
// Other operators are provided automaticly:
assert(a <= b);
assert(b > a);
assert(b >= a);
assert(a != b);
}
1

Другие решения

Без использования наддува:

#include <cassert>
struct Integer
{
int value;
Integer(int x) : value(x) {}
};

bool operator<(Integer lhs,Integer rhs)
{
return lhs.value < rhs.value;
}
bool operator==(Integer lhs,Integer rhs)
{
return lhs.value == rhs.value;
}

template< class T >
bool operator!= (const T& L, const T& R) { return !(L==R); }
template< class T >
bool operator<= (const T& L, const T& R) { return (L < R) || (L == R); }
template< class T >
bool operator>  (const T& L, const T& R) { return (!(L < R)) && (!(L == R)); }
template< class T >
bool operator>= (const T& L, const T& R) { return !(L < R); }

int main()
{
Integer a(1), b(2), c(1);
assert(a < b);
assert(a <= b);
assert(b > a);
assert(b >= a);
assert(a == c);
assert(a != b);
}

Или ближе к вашему первоначальному вопросу:

#include <cassert>
struct Integer {
int value;
Integer(int x) : value(x) {}
int compare(const Integer & rhs) const {
return (value - rhs.value);
}
};

template< class T >
bool operator== (const T& L, const T& R) { return L.compare(R)==0; }
template< class T >
bool operator!= (const T& L, const T& R) { return L.compare(R)!=0; }
template< class T >
bool operator<  (const T& L, const T& R) { return L.compare(R)<0; }
template< class T >
bool operator<= (const T& L, const T& R) { return L.compare(R)<=0; }
template< class T >
bool operator>  (const T& L, const T& R) { return L.compare(R)>0; }
template< class T >
bool operator>= (const T& L, const T& R) { return L.compare(R)>=0; }

int main() {
Integer a(1), b(2), c(1);
assert(a < b);
assert(a <= b);
assert(b > a);
assert(b >= a);
assert(a == c);
assert(a != b);
}
0

Самое близкое, я думаю, что вы можете получить, это предоставить операторы для базового класса и требовать, чтобы все сопоставимые классы наследовали от него. Реализация их как шаблонных свободных функций не совсем хорошая идея, так как это позволит компилятору попытаться выполнить операцию не только над интересующими вас типами.

class AClass
{
public:
int compare(const AClass& a) const
{
return this == &a ? 0 : 1; // i'm sure you can do the -1 / 1 stuff
}

friend bool operator==(const AClass& L, const AClass& R)
{
return L.compare(R) == 0;
}
};

Это позволит сравнивать AClass и всех потомков.

0
По вопросам рекламы [email protected]