LINUX.ORG.RU

Почему оператор != не генерируется автоматически, если определен == ?

 , ,


1

5

Собственно сабж. Вообще логично было бы определять логически противоположные операторы обоюдной негацией (отрицанием?):

struct Comparable {
  // имеем определенный оператор ==
  template <typename T>
  bool operator ==(const T &rhs) const { /* ... */ }

  // тогда было бы логично implicit определить
  template <typename T>
  bool operator !=(T&& rhs) const { 
    return !this->operator ==(std::forward<T>(rhs)); 
  }

  // ну или explicit
  template <typename T>
  bool operator !=(const T&) = default;
};

Я тут сварганил пример (естественно без шаблонов, чтоб меньше потенциальных ошибок): https://wandbox.org/permlink/a4k0hlNVI4UgyDrc

И, как можно видеть, оператор != не определяется автоматически. Вопрос: почему, ЧЯДНТ?

P.S. Нашел на stackoverflow предложение которое не вошло в С++17) но решило бы волпрос: Explicitly defaulted comparison operators

На сколько мне известно, неявные определения операторов сравнения сторятся от оператора «<».

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

неявные определения операторов сравнения сторятся от оператора «<».

Ну, с помощью < можно сделать heap sort и далее set. Что, например, std::set и делает. Алгоритм в std::set быть может и не конкретно heap sort, но operator < он использует явно (и никаких других). Т.е. компилятор не доопределяет в таком случае ничего.

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

потому что == может удалять элемент из списка, а не сравнивать

И правда нет ограничений что this должно быть const. Быть может даже можно нафантазировать вменяемую семантику для такого ==.

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

Прикольно. Только выходит что оно сразу для всех типов определяет операторы, если использовать неаккуратно.

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

оператор != не определяется автоматически
потому что == может удалять элемент из списка, а не сравнивать

Господа разработчики программ, господа разработчики программ для разработчиков, господа архитекторы языков. Вы чё там все курите я хочу спросить?

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

Вообще, во многих случаях было бы неплохо иметь _синтезируемые_ методы сравнения, определяемые как объединение результатов сравнения подобъектов(т. е. объекты эквивалентны когда эквивалентны все их соответствующие подобъекты). Но это не всегда приемлемо. С доопределением похожие проблемы(выше уже были неплохие примеры на эту тему), поэтому такой костылик сделали.

P. S. using namespace std::rel_ops; даст в точности тот эффект, о котором ты говоришь. Только

если использовать неаккуратно

о возможных проблемах ты сам сказал...

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

Вы чё там все курите я хочу спросить?

Такая возможность есть технически, никто ж не говорит что надо вот прям так и делать :-)

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

Что-то никто не упомянул, что std::rel_ops будут deprecated в C++20, в пользу <=> (синтезируется по = default, если поля это позволяют).

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

Я даже c++17 ещё толком не смотрел. А с новой фичей да, rel_ops не нужен(насколько показал беглый просмотр)

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

Я даже c++17 ещё толком не смотрел. А с новой фичей да, rel_ops не нужен(насколько показал беглый просмотр)

И не смотри :-) Цепепе не нужен даже с новой фичей :-) Лол :-)

anonymous
()
Ответ на: комментарий от thunar
bool MyClass::operator==(int elem){
    if (list.isExist(elem)){
        list.remove(elem);
        return true; // Операция завершена успешно
    }
    return false; // Элемент elem не найден в списке
}
SR_team ★★★★★
()
Последнее исправление: SR_team (всего исправлений: 1)
Ответ на: комментарий от anonymous

Смайлофаг!

Цепепе не нужен

Ну это давно ясно :-) Но глянуть можно :-)

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

синтезируется по = default, если поля это позволяют

Тогда вообще не вижу причин не заимплементировать предложение «Explicitly defaulted comparison operators» из шапки топика в С++20.

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

Тогда вообще не вижу причин не заимплементировать предложение «Explicitly defaulted comparison operators» из шапки топика в С++20.

Ну да :-) И почему они не обратились к экспертам ЛОРа за консультацией? :-) Лол :-)

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

Ну <=> так и делает, только не по штукам, а по группам: strong ordering, weak ordering, etc.

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

[humor]
Я еще вот семантику придумал: https://wandbox.org/permlink/Jcy2VrOaIoFhV3cw

template <typename Key, typename T, typename... Others>
class MyMap : public std::map<Key, T, Others...> {
public:
    using ParentType = std::map<Key, T, Others...>;

    using ParentType::ParentType;

    T&& operator==(const Key &key) {
        auto node = ParentType::extract(key);
        if (node.empty())
            throw std::out_of_range("no such key");
            
        return std::move(node.mapped());
    }
};

// оператор "труба" -- "вытягивает" елемент из контейнера
std::string two = map == 2;

[/humor]

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

И почему они не обратились к экспертам ЛОРа за консультацией? :-)

Да у меня уже подгорает, скоро бомбанет :-) Такой талантище пропадает :-) Тратит свое время на ответы анонимусу-смайлофагу :-)

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

Неверно. Сравнение с NULL даёт NULL, а не false. Но это по хорошему, без провалов с троичной логики обратно в двоичную

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

Жесть какая. Всегда думал, что они с const определяются...

thunar ★★★★★
()

потому что != != !==

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

Хорошим примером будет NaN в том же C++, для которого == и != оба должны давать false. Но это крайний случай, который не должен мешать удобству.

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

Но и обратного тоже не налагает

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

ты упоротый что ли? ты сам сделал == не const в своём отдельном примере, и на этом основании заявляешь, что он всегда будет что-то удалять. а я вот всегда пишу

bool operator ==(const T& t) const {...}

и у меня всегда можно сделать оператор !=

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

ты упоротый что ли?

Ну... Э-э-э... А, вот! Лол :-)

ты сам сделал == не const в своём отдельном примере

Но это же не мой пример!?

всегда будет что-то удалять

Вот покажи хоть один коммент, где речь шла про всегда/должен, а не про иногда/может? Никто ж не говорил, что всегда так делать надо

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

ты сам сделал == не const в своём отдельном примере,

Знаешь про mutable, да? Хоть С++ не заставляет програмистов гадить в исходники, но и не запрещает.

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

Разве что когда я обезумею и начну бегать по улицам с ведром на голове. Операторы можно перегружать но всё таки надо делать это так, чтоб вид оператора как то соответствовал его наполнению. А то ведь можно сравнение на оператор плюс повесить, нехай те кто будут потом код читать, с ума сойдут.

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

чтоб вид оператора как то соответствовал его наполнению

Ага, operator+() для строк таки соответствует. И можно определить operator-() как l + (-r))

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

Объясняю на пальцах. Пусть у тебя есть класс точка, в котором есть всего два мембера: икс и игрек. Если ты реализуешь оператор != как отрицание то ты ничего не теряешь в скорости.

Но пусть у тебя есть класс ну допустим я даже не знаю. Пусть это логин на сервере. И он удостоверяется через асимметричную крипту плюс через список отозванных логинов. Чтоб узнать что входной логин не равен такому в памяти, надо затратить эн усилий. А чтоб узнать что он равен надо затратить эн усилий да ещё сходить в базу данных. В этом случае имеет смысл делать эти операторы разными.

ckotinko ☆☆☆
()
Ответ на: комментарий от Deleted

Да. Прибавить к строке это понятно и очевидно что в результате к строке что то присобачить сзади. Вычесть из строки уже не очевидно и оператора такого нету.

Наличие возможности в с++ не надо воспринимать как приглашение к вандализму.

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

И? Минус очевидным образом не доопределяется. Точно такая же ситуация со сравнением может быть.

Прибавить к строке это понятно и очевидно что в результате к строке что то присобачить сзади

Только вследствие того, что этот пример из стандартной библиотеки

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

Вот объясни мне, как ты это делаешь. В треде есть мнение, что доопределение не всегда возможно из-за возможного необычного содержания operator==(). Ты говоришь: это программист г., если писать по нормальному(интуитивно понятно) - проблем не возникает. А ещё ты говоришь, что + для строк написан нормально(интуитивно понятно). Но минус доопределить всё равно нельзя. Определись уже: либо + г., либо минус можно спокойно доопределить(в этом случае покажи как)

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

И в чём проблема реализовать оператор == используя те же быстрые проверки на неравенство? А оператор != уже соответственно как отрицание?

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

Смысл делать операторы разными очевиден с первого взгляда на заголовок, и NaN тому — хрестоматийный пример.

Вопросы лежат исключительно в плоскости (как выясняется) добровольного сранья руками в исходники на C++. Практика ведь настолько распространена, что не удивлюсь, если увижу ее в очередном стандарте.

t184256 ★★★★★
()

Не думал, что кто-то сможет переплюнуть ckotinko в поехавшести, но в этом треде такой контингент собрался, что он (не контингент) выглядит самым адекватом.

utf8nowhere ★★★
()
Последнее исправление: utf8nowhere (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.