Ответ 1
С появлением С++ 11 появился новый и лаконичный способ достижения этого, используя std:: tie:
bool operator<(const MyData& other) const {
return std::tie(surname, forename) < std::tie(other.surname, other.forename);
}
Если у меня есть класс, который я хочу, чтобы сортировать (т.е. поддерживать менее концепцию), и он имеет несколько элементов данных, так что мне нужно делать лексикографическое упорядочение, тогда мне нужно что-то вроде этого:
struct MyData {
string surname;
string forename;
bool operator<(const MyData& other) const {
return surname < other.surname || (surname==other.surname && forename < other.forename); }
};
Это становится довольно неуправляемым для чего-либо с более чем двумя членами данных. Есть ли более простые способы его достижения? Элементами данных могут быть любые классы Comparable.
С появлением С++ 11 появился новый и лаконичный способ достижения этого, используя std:: tie:
bool operator<(const MyData& other) const {
return std::tie(surname, forename) < std::tie(other.surname, other.forename);
}
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
-invocations.
Вы можете сохранить данные в boost::tuple
, который обеспечивает лексикографическое сравнение, и предоставить именованные функции доступа по строкам:
#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
в следующем стандарте.
Поддержание списка аксессуаров, вероятно, более управляемо, чем поддержание кода сравнения.
Если все члены имеют один и тот же тип, вы можете поместить их в std::vector
. По умолчанию std::lexicographical_compare
будет использоваться для сравнения векторов.
Вы можете использовать boost::tuple
или std::pair
, который имеет встроенное лексиграфическое сравнение. Конечно, недостатком является то, что вы не можете связать метод с кортежами.