Если у меня есть класс, который я хочу смочь отсортировать (т.е. поддерживать меньше понятие), и оно имеет несколько элементов данных, таким образом, что я должен сделать лексикографическое упорядочивание затем, мне нужно что-то вроде этого:
struct MyData {
string surname;
string forename;
bool operator<(const MyData& other) const {
return surname < other.surname || (surname==other.surname && forename < other.forename); }
};
Это становится довольно неуправляемым для чего-либо больше чем с 2 элементами данных. Есть ли какие-либо более простые способы достигнуть его? Элементы данных могут быть любым Сопоставимым классом.
Вы можете хранить данные в boost :: tuple
, который обеспечивает лексикографическое сравнение и предоставляет именованные функции доступа в соответствии со строками of:
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
struct Data {
string &surname() {return stuff.get<0>();}
string &forename() {return stuff.get<1>();}
// it would be polite to add const overloads too.
bool operator<(const Data &other) const {return stuff < other.stuff;}
private:
boost::tuple<string, string> stuff;
};
Я считаю, что это также доступно как std :: tr1 :: tuple
, и будет std :: tuple
в следующем стандарте.
Поддерживать список средств доступа, вероятно, проще, чем поддерживать код сравнения.
tuple
- хорошая идея, но если вы хотите сохранить имена для ваших переменных-членов, возможно, будет достаточно перестроить вашу функцию сравнения следующим образом:
struct MyData {
string surname;
string forename;
string var;
// ...
bool operator<(const MyData& other) const {
if (surname != other.surname) return surname < other.surname;
if (forename != other.forename) return forename < other.forename;
if (var != other.var) return var < other.var;
// ...
return false; //< They are equal
}
};
В зависимости от вашего вкуса, вы можете даже захотеть макрос типа #define COMPARE(field) if (field != other.field) return field < other.field;
чтобы уменьшить дублирование. Тогда функция просто превратится в список COMPARE
-вызовов.
Если все члены имеют один и тот же тип, вы можете поместить их в std :: vector
. По умолчанию для сравнения векторов будет использоваться std :: lexicographic_compare
.
Вы можете использовать boost :: tuple
или std :: pair
со встроенным лексиграфическим сравнением. . Конечно, недостатком является то, что вы не можете связать метод с кортежами.