LINUX.ORG.RU

Почему operator<=>() не генерирует operator==()?

 


1

2
struct X {
    std::string s;
    inline auto operator <=>(const X& x) const { return s <=> x.s; }
};

https://godbolt.org/z/E8Y5Y3bs5

В итоге определены все операции сравнения кроме ==. (Во, теперь ещё и != неопределён. Только что ж пробовал.) Наличие constructor/assignment не влияет.

И самое смешное, в точно такой же структуре (с конструкторами, объявлена внутри namespace dimgel и по-другому называется) в моём проекте не определён ещё и operator<(). Что это за долбаная магия?

★★★★★

Последнее исправление: maxcom (всего исправлений: 5)

во что они превратили мой старый добрый цепепе-98, сволочи!

что этот оператор хоть делает? :)

Harald ★★★★★
()
Ответ на: комментарий от Harald

что этот оператор хоть делает? :)

Я вот как раз и не …ээээ… понимаю. Что он должен делать – по идее – так это генерить все операторы сравнения одним махом.

dimgel ★★★★★
() автор топика

Во всяких строка и других стд контейнерах решено делать == отдельно, ибо <=> дорогой, во всяких алгоритмах с миллиоными циклами может быть ощутимо.

kvpfs ★★
()
Ответ на: комментарий от rupert

Спасибо. ) Вполне в духе C++ дурацкое (в смысле ни хрена не интутивное) решение.

dimgel ★★★★★
() автор топика
Последнее исправление: dimgel (всего исправлений: 1)
Ответ на: комментарий от kvpfs

Не вижу как это коррелирует с тем фактом, что default-реализация его таки объявляет. LTO по идее должен вывезти, если программист сам понимает что делает. А если не понимает, то и отдельное объявление == ему не поможет.

dimgel ★★★★★
() автор топика
Последнее исправление: dimgel (всего исправлений: 2)
Ответ на: комментарий от dimgel

Как знаешь, тебе видней, наверное. Я как-то натыкался на очень годную статью по этому поводу, вспомнить не могу сейчас, можешь погуглить, где-то она есть.

kvpfs ★★
()
Ответ на: комментарий от anonymous

а может ты анонимус ещё больший олдфаг, кто знает

Harald ★★★★★
()
Ответ на: комментарий от dimgel

Не вижу как это коррелирует с тем фактом, что default-реализация его таки объявляет.

Видимо имеется ввиду, что default <=> генерит не «дефолтный <=> с выведением из него всех остальных» а «дефолтные все», могущие и не иметь общего <=>.

firkax ★★★★★
()

вообще-то оператор == более базовый, чем <=>.

равенство(идентичность в той или иной форме) определено вообще на любом множестве. а <=> определен только на упорядоченном множестве. то есть оператор <=> «слабее», чем ==.

видимо потому определение <=> не определяет ==, а из == выводится !=

alysnix ★★★
()
Ответ на: комментарий от alysnix

С производительностью вопросы тоже есть - нельзя написать одинаково эффективно все операторы сравнения, нам всегда надо будет сравнивать две строки (для примера) лексикографически тогда как в случае operator== можно обойтись сравнением их size()’ов. Например имеем: «hello» == «hello world» зачем здесь проходить все символы в цикле с целью узнать кто же там первее, если можно быстро сравнить размеры? Очевидный оверхед.

kvpfs ★★
()
Ответ на: комментарий от alysnix

*сильнее/строже а не слабее. Потому что <=> задает более узкую категорию.

anonymous
()
Ответ на: комментарий от NAY_GIGGER

Ну вообще-то в C++ изменения обычно обратно совместимы. Т.е. за исключением очень редких случаев код, написанный для C++98 должен работать и в сборке с C++20.

С другой стороны, я могу понять попаболь при виде кода, где используются фичи новых стандартов, если чел ни ухом ни рылом об этих новых стандартах не слышал. И даже статьи Райнера Гримма не осилил прочитать.

seiken ★★★★★
()
Последнее исправление: seiken (всего исправлений: 1)
Ответ на: комментарий от dimgel

Блин ну и зачем это нужно, все одним махом генерить? Если людям лень писать самим - для них есть Java,C#, на худой конец Rust или Питон - там вообще малословно.

bonta ★★★★★
()
Ответ на: комментарий от bonta

Если людям лень писать самим

Если не лень писать самим, то можешь добавить поддержку старых стандартов, больше строчек богу строчек :)

пример:

#if _HAS_CXX20
    _NODISCARD constexpr strong_ordering operator<=>(const _Array_const_iterator& _Right) const noexcept {
        return _Ptr <=> _Right._Ptr;
    }
#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv
    _NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept {
        return !(*this == _Right);
    }

    _NODISCARD _CONSTEXPR17 bool operator<(const _Array_const_iterator& _Right) const noexcept {
        return _Ptr < _Right._Ptr;
    }

    _NODISCARD _CONSTEXPR17 bool operator>(const _Array_const_iterator& _Right) const noexcept {
        return _Right < *this;
    }

    _NODISCARD _CONSTEXPR17 bool operator<=(const _Array_const_iterator& _Right) const noexcept {
        return !(_Right < *this);
    }

    _NODISCARD _CONSTEXPR17 bool operator>=(const _Array_const_iterator& _Right) const noexcept {
        return !(*this < _Right);
    }
#endif // !_HAS_CXX20

https://github.com/microsoft/STL/blob/b11945b73fc1139d3cf1115907717813930cedbf/stl/inc/array#L115-L139

fsb4000 ★★★★★
()
Ответ на: комментарий от kvpfs

нельзя написать одинаково эффективно все операторы сравнения, нам всегда надо будет сравнивать две строки (для примера) лексикографически тогда как в случае operator== можно обойтись сравнением их size()’ов

Вот так понятней, сенькс. Хотя собственно решение не генерить == всё равно под вопросом: если программист может написать более оптимальный ==, дык пусть рядышком с <=> и напишет, а компилятор в этом случае не будет генерить == из <=>. (Полагаю, так и сейчас: кастомное имеет более высокий приоритет чем сгенерированное из <=>.) А в подклассах <=> тогда должен подцепить этот кастомный «оверлоад».

dimgel ★★★★★
() автор топика
Ответ на: комментарий от kolpakchi

Контейнеры хранят свой размер, зачем тут какие-то доп телодвижения.

kvpfs ★★
()
Ответ на: комментарий от anonymous

ну не будь инфоцыганом, будь инфоевреем. Какие проблемы?

seiken ★★★★★
()
Ответ на: комментарий от dimgel

а компилятор в этом случае не будет генерить == из <=>

при auto operator<=>(const X& x) const = default; компилятор генерирует две фунции,

operator <=> и operator ==

и для == не используется <=>, а != определена как !(a==b).

https://godbolt.org/z/57EzGqoda

даже если оператора == нет, то всё равно не будет выводиться через <=>, а будет ошибка: https://godbolt.org/z/xefEhE6b8

fsb4000 ★★★★★
()

Срамота. Кресты напоминают стареющую лядь, которая нафигачивает в себя все больше и больше силикона и каждый новый драфт как еще одна неудачная пластика, лол.

anonymous
()
Ответ на: комментарий от anonymous

Потому что разработкой стандарта занимаются компании типа microsoft, которые ничего не понимают ни в проектировании ни в языках программирования ни в написании программ. Они пихают в язык костыли для своих сиюминутных задач, потом через пять лет их забывают и пихают новые.

А действительно важные предложения лежат десяток лет без стандартизации.

anonymous
()
Ответ на: комментарий от anonymous

Они пихают в язык костыли

Кстати о птичках: по уму <=> следовало бы реализовать макросом (настоящим, AST-шным), без утяжеления собственно языка. Помнится, не успели в скалу впилить макросы, тут же сообщили что некоторые части компилятора переписываются и упрощаются с их помощью.

Вот впилили бы в C++ полноценное метапрограммирование (вместо нынешней constexpr-по#@#ни), и тонны костылей ушли бы в библиотеки: хочешь юзай, хочешь нет, хошь альтернативу напиши.

dimgel ★★★★★
() автор топика
Ответ на: комментарий от dimgel

Мне кажется, что ты не понял, что <=> не генерит набор операторов на все случаи сравнения, он лишь берёт на себя их функию и дёргается вместо них. Можешь не пользоваться и писать 4 оператора вместо одного.

Вот впилили бы в C++ полноценное метапрограммировани

Ничего, что нет единого, эталонного компилятора? Тебе никто не мешает закостылить свой плагин и привязаться гвоздями к шлангу, например.

вместо нынешней constexpr-по#@#ни

А это чем тебе не угодило? Как AST макросы могут заменить constexpr? Например, хочу распарсить текст в компайлтайме, на что мне нужно натянуть AST макросы?

kvpfs ★★
()
Ответ на: комментарий от seiken

Т.е. за исключением очень редких случаев код, написанный для C++98 должен работать и в сборке с C++20.

На практике часто либо девелоперы об этом подумали и вкинули макросов, которые позволят ему работать, либо 98-й код написан в слишком пермиссивной манере :)

slackwarrior ★★★★★
()
Ответ на: комментарий от kvpfs

Мне кажется, что ты не понял, что <=> не генерит набор операторов на все случаи сравнения, он лишь берёт на себя их функию и дёргается вместо них.

Сенькс.

Ничего, что нет единого, эталонного компилятора?

Зато есть единый эталонный стандарт. Могли бы в него впилить. Или там всё настолько плохо, что даже на уровне структур AST договориться невозможно?

Тебе никто не мешает закостылить свой плагин и привязаться гвоздями к шлангу, например.

Это я в курсе.

Например, хочу распарсить текст в компайлтайме, на что мне нужно натянуть AST макросы?

AST-макросы – это код, выполняемый в компайл-тайм. Полноценный код. Произвольный. Хочешь распарсить текст – берёшь и парсишь. На нормальном языке, а не костыльном подмножестве.

dimgel ★★★★★
() автор топика
26 октября 2022 г.
Ответ на: комментарий от dimgel

Вот впилили бы в C++ полноценное метапрограммирование (вместо нынешней constexpr-по#@#ни), и тонны костылей ушли бы в библиотеки: хочешь юзай, хочешь нет, хошь альтернативу напиши.

так они и делают отход от костылей, — к примеру вместо всяких SFINAE штучек теперь можно использовать человеческие concepts.

safocl ★★
()
Ответ на: комментарий от safocl

Вот впилили бы в C++ полноценное метапрограммирование, и тонны костылей ушли бы в библиотеки

так они и делают отход от костылей, — к примеру вместо всяких SFINAE штучек теперь можно использовать человеческие concepts

concepts – безусловно человеческие, но к метапрограммированию относятся примерно никак, т.к. являются частью языка, а не средством трансформации кода программы.

А точнее, concepts – это инструмент статической типизации, а не МП.

dimgel ★★★★★
() автор топика
Последнее исправление: dimgel (всего исправлений: 1)
16 декабря 2022 г.
Ответ на: комментарий от dimgel

немного не согласен — ибо концепт, хоть по своей природе и является частью языка (ключевое слово) — но все же его роль для метапрограммирования очень велика. Многие годы его роль костылировали путем SFINAE механизма. Concepts не считаю инструментом статической типизации, поскольку он всего лишь накладывает некоторые ограничения на использование в шаблонах типов.

safocl ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.