Как определить operator<
в n-кортеже (например, на 3-кортеже), чтобы он удовлетворял концепции строгого слабого упорядочения? Я знаю, что библиотека boost имеет класс кортежа с правильно определенным operator<
, но по некоторым причинам я не могу его использовать.
Оператор <и строгий слабый порядок
Ответ 1
if (a1 < b1)
return true;
if (b1 < a1)
return false;
// a1==b1: continue with element 2
if (a2 < b2)
return true;
if (b2 < a2)
return false;
// a2 == b2: continue with element 3
if (a3 < b3)
return true;
return false; // early out
Это упорядочивает элементы по a1 как наиболее значимым и a3 наименее значимым.
Это может быть продолжено до бесконечности, вы также можете, например, применить его к вектору T, повторяя сравнения a [i] <a [i + 1]/a [i + 1] <a [i]. Альтернативное выражение алгоритма будет "пропустить при равенстве, затем сравнить":
while (i<count-1 && !(a[i] < a[i+1]) && !(a[i+1] < a[i])
++i;
return i < count-1 && a[i] < a[i+1];
Конечно, если сравнение дорого, вы можете кэшировать результат сравнения.
[править] удален неправильный код
[править] Если доступно больше, чем просто operator<
, я склонен использовать шаблон
if (a1 != b1)
return a1 < b1;
if (a2 != b2)
return a2 < b2;
...
Ответ 2
строгий слабый порядок
Это математический термин для определения отношений между двумя объектами.
Его определение таково:
Два объекта x и y эквивалентны, если оба f (x, y) и f (y, x) являются ложными. Обратите внимание, что объект всегда (по инварианту нерефлексивности) эквивалентен самому себе.
В терминах C++ это означает, что если у вас есть два объекта данного типа, вы должны вернуть следующие значения при сравнении с оператором <.
X a;
X b;
Condition: Test: Result
a is equivalent to b: a < b false
a is equivalent to b b < a false
a is less than b a < b true
a is less than b b < a false
b is less than a a < b false
b is less than a b < a true
То, как вы определяете эквивалент/меньше, полностью зависит от типа вашего объекта.
Формальное определение:
Строгий слабый порядок
Информатика:
Строгий Слабый Заказ
Как это относится к операторам:
компаратор
Ответ 3
... новый ответ на очень старый вопрос, но существующий ответ пропустил простое решение из С++ 11...
Решение С++ 11
С++ 11 предоставляет std::tuple<T...>
, который вы можете использовать для хранения ваших данных. tuple
имеют соответствующий operator<
, который первоначально сравнивает самый левый элемент, затем работает вдоль кортежа, пока результат не станет понятным. Это подходит для обеспечения строгого слабого упорядочения, ожидаемого, например, std::set
и std::map
.
Если у вас есть данные в некоторых других переменных (например, поля в struct
), вы можете даже использовать std::tie()
для создания кортежа ссылок, который затем можно сравнить с другим таким кортежем. Это упрощает запись operator<
для определенных полей данных элемента в пользовательском типе class
/struct
:
struct My_Struct
{
int a_;
double b_;
std::string c_;
};
bool operator<(const My_Struct& lhs, const My_Struct& rhs)
{
return std::tie(lhs.a_, lhs.b_, lhs.c_) < std::tie(rhs.a_, rhs.b_, rhs.c_);
}
Ответ 4
Вы могли бы просто использовать трехэлементные векторы, которые уже будут иметь оператор <() соответственно определены. Это имеет то преимущество, что оно распространяется на N-элементы без необходимости делать что-либо.
Ответ 5
Основной поток должен быть по строкам: если элементы Kth разные, возврат меньше, чем другой, перейдите к следующему элементу. В приведенном ниже коде предполагается, что у вас нет бут-кортежа, иначе вы бы использовали get<N>(tuple)
и не имели проблемы для начала.
if (lhs.first != rhs.first)
return lhs.first < rhs.first;
if (lhs.second != rhs.second)
return lhs.second< rhs.second;
return lhs.third < rhs.third;
Ответ 6
Даже если вы не можете использовать ускоренную версию, вы сможете пропустить код. Я отказал это от std:: pair - 3 кортежа будут похожи, я думаю.
return (_Left.first < _Right.first ||
!(_Right.first < _Left.first) && _Left.second < _Right.second);
Изменить: как заметили несколько человек, если вы крадете код из стандартной библиотеки, чтобы использовать ее в своем коде, вы должны переименовать вещи, у которых есть подчеркивания спереди, поскольку эти имена зарезервированы.