Кресты / Говнокод #27397 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
// https://habr.com/ru/company/yandex_praktikum/blog/555704/
// Стандарт C++20: обзор новых возможностей C++. Часть 2 «Операция ''Космический Корабль''»

// Предположим, вы определили структуру, содержащую одно число:

struct X {
    int a;
};

// Мы хотим сделать так, чтобы значения этой структуры можно было сравнивать друг с другом.
// Для этого придётся написать шесть операций:

bool operator== (X l, X r) { return l.a == r.a; }
bool operator!= (X l, X r) { return l.a != r.a; }
bool operator>= (X l, X r) { return l.a >= r.a; }
bool operator<= (X l, X r) { return l.a <= r.a; }
bool operator< (X l, X r) { return l.a < r.a; }
bool operator> (X l, X r) { return l.a > r.a; }

// А теперь представьте, что мы хотим сравнивать элементы этой структуры не только между собой,
// но также с числами int. Количество операций возрастает с шести до 18:

bool operator== (X l, int r) { return l.a == r; }
bool operator!= (X l, int r) { return l.a != r; }
bool operator>= (X l, int r) { return l.a >= r; }
bool operator<= (X l, int r) { return l.a <= r; }
bool operator< (X l, int r) { return l.a < r; }
bool operator> (X l, int r) { return l.a > r; }

bool operator== (int l, X r) { return l == r.a; }
bool operator!= (int l, X r) { return l != r.a; }
bool operator>= (int l, X r) { return l >= r.a; }
bool operator<= (int l, X r) { return l <= r.a; }
bool operator< (int l, X r) { return l < r.a; }
bool operator> (int l, X r) { return l > r.a; }

// Что делать? Можно позвать штурмовиков. Их много, и они быстро напишут 18 операций.

// Или воспользоваться «космическим кораблём». Эту новую операцию в C++ называют
// «космический корабль», потому что она на него похожа: <=>. Более формальное название
// «трёхстороннее сравнение» фигурирует в документах Стандарта.

А можно добавить гомоиконность, которой можно наметушить не только какой-то там космический корабль (ради которого в крестокомпиляторах надо синтаксический анализатор менять, чтоб добавить новое синтаксиальное говно для этого <=>), а хоть целую, блядь, эскадрилью космических кораблей, которая работает не только для "больше меньше равно", но и для любой вообразимой поебени

Но крестушкам конечно привычней добавить какой-то ad-hoc хуиты для частных случаев.

Запостил: j123123 j123123, (Updated )

Комментарии (9) RSS

  • Как в Perl:)

    То есть теперь не нужно вручную объяснять компилятору, что если A > B, то B < A, а можно сделать одну фцнкйию, которая вернет -1, 0 и 1? Типа "меньше", "равно", "больше"?
    Ответить
    • > То есть теперь не нужно вручную объяснять компилятору, что если A > B, то B < A, а можно сделать одну фцнкйию, которая вернет -1, 0 и 1? Типа "меньше", "равно", "больше"?

      Нет, не совсем так. Это крестоговно, тут всё сложнее.
      Ответить
      • https://habr.com/ru/company/yandex_praktikum/blog/555704/#comment_23001838
        > Это не совсем так, причина там в другом. Оператор <=> вообще никогда не генерирует операторы == и != сам по себе, он генерирует только <, >, <= и >=, при этом неважно, какой ордеринг применяется. Просто есть соглашение, что дефолтные операторы == и != генерируются как бы «в довесок», если оператор <=> определен как defaulted, а так операторы «сравнения» и «равенства» как бы логически разделены и независимы. Идея была в том, что к результату выполнения operator<=>() предъявляются определенные требования, которые могут быть игнорированы при сравнении «на равенство», скажем, векторов или строк. Можно определить, что один вектор не равен другому, просто сравнив длину, и если длины разные, то сразу остановиться. Поэтому было решено, что не следует пользоваться кастомной реализацией operator<=>() для создания дефолтной реализации операторов сравнения на строгое равенство. В случае кастомной реализации operator<=>() по-прежнему можно при желании явным образом определить operator==() как default и получить его (и != соответственно). Вот здесь подробнее написано:

        http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1185r2.html
        Ответить
      • Скажем, если взять какие-нибудь плавучиепитуховые числа, и сравнивать их, то если "false == (NaN == NaN)" и "false == (NaN < NaN)" то это еще не значит, что "true == (NaN > NaN)". Охуенно, не правда ли?
        Ответить
  • > Пример

    > В структуру X я добавил всего одну строчку, определяющую операцию <=>. Заметьте, что я даже не написал, что именно она делает:

    #include <iostream>
    
    struct X {
        auto operator<=>(const X&) const = default; // <-- !
        int a;
    };


    > И C++ всё сделал за меня. Это сработает и в более сложных случаях, например, когда у X несколько полей и базовых классов. При этом всё, что есть в X, должно поддерживать сравнение.

    Да, охуеть конечно, ничего не скажешь. А под что-то кроме сравнения ее можно использовать? Почему надо под какую-то мелкую частную поебень со сравнением через "<" "==" ">" пилить какую-то частную хуйню?
    Ответить
    • Стесняюсь спросить: а если я определю оператор <=> и оператор <=, то что будет?
      Ответить
      • ЕМНИП <=> используется если явно не определён соответствующий оператор.

        Но это не точно, потому что я это не использую. Самое ненужное добавление ИМХО. Лучше бы рефлексию запилили.
        Ответить
        • > Самое ненужное

          Сам оператор нинужен, конечно. А вот = default для операторов сравнения выглядит вполне няшно, наконец-то не надо будет генерить эту фигню макросами и перечислять поля для сравнения вручную.
          Ответить

Добавить комментарий

Из-за тебя ушел bormand, guest!

    А не использовать ли нам bbcode?


    8