Зачем std :: rel_ops нужен оператор равенства? - PullRequest
0 голосов
/ 16 февраля 2019

Почему равенство необходимо для rel_ops?Разве «<» недостаточно? </p>

a==b => !(a<b) && !(b<a)

Это может быть очень глупый вопрос.Я что-то упустил?

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Да, на самом деле вам не хватает чего-либо.И это очень фундаментально.Это не о C ++ или программировании.Это о математике.Согласно математике, ваше утверждение истинно тогда и только тогда, когда «<» определяет строгий <a href="https://en.wikipedia.org/wiki/Weak_ordering?wprov=sfla1" rel="nofollow noreferrer"> слабый порядок в области своего операнда.Не каждый пользовательский тип со значением "less" rel_op имеет слабый порядок.

0 голосов
/ 16 февраля 2019

Почему равенство необходимо для rel_ops?Разве «<» недостаточно? </p>

a==b => !(a<b) && !(b<a)

Потому что в общем случае это не так.Если бы rel_ops работал бы только для реляционных операторов, которые следуют этой логике, он был бы весьма ограничен.

Я предполагаю, что вы имеете в виду слабый порядок, требуемый для оператора < для ассоциативных контейнеров.Из cppreference :

Везде, где стандартная библиотека использует требования сравнения, уникальность определяется с использованием отношения эквивалентности.В неточных терминах два объекта a и b считаются эквивалентными (не уникальными), если ни один из них не сравнивается меньше, чем другой:! Comp (a, b) &&! Comp (b, a).

Inпростые термины: то, считаются ли два ключа «одинаковыми», определяется только требованием ! (a < b) && ! (b < a).Следовательно, вам нужно только указать < для ассоциативных контейнеров и не указывать operator==, чтобы решить, являются ли два ключа одинаковыми.Однако эквивалентность (!(a<b)&&!(b<a)) не обязательно совпадает с равенством (a==b).

Например, когда вы используете этот

struct my_key {
    int a;
    int b;
    bool operator< (const key_type& other) {
        return a < other.a;   // not comparing b !
    }
};

в качестве ключа std::mapтогда my_key{1,0} и my_key{1,2} эквивалентны («тот же ключ»), даже если они не равны.В качестве другого примера рассмотрим Point в сферических координатах, где мы выбираем a < b, когда a ближе к началу координат, чем b:

struct Point {
    double radius;
    double angle;
    bool operator<(const Point& other) { 
        return radius < other.radius; 
    }
    bool operator==(const Point& other) {
        return (radius == other.radius) && (angle == other.angle);
    }
}

Также здесь все три a < bb < a и a == b могут быть ложными одновременно.

Также обратите внимание, что (из cppreference )

Начиная с C ++ 20, std :: rel_ops устарел в пользу оператора <=>.

Для звездолета <=> вы можете выбрать между

std::strong_ordering 
std::weak_ordering
std::partial_ordering
std::strong_equality 
std::weak_equality  

Слабый заказ - это то, что требуется, например, для std::map (например, my_keyили Point), тогда как для сильного порядка эквивалентность и равенство в основном одинаковы.Для более подробной информации и примеров я отсылаю вас к this .

...