Гарантирует ли стандарт C++, что (x!=y)
всегда имеет то же значение истинности, что и !(x==y)
?
Я знаю, что здесь задействовано много тонкостей: операторы ==
и !=
Могут быть перегружены. Они могут быть перегружены, чтобы иметь разные типы возврата (которые должны быть неявно конвертируемыми в bool
). Даже то !
-operator может быть перегружен в типе возврата. Вот почему я хрупко упомянул "ценность истины" выше, но попытался развить ее дальше, используя неявное преобразование в bool
и пытаясь устранить возможные неясности:
bool ne = (x!=y);
bool e = (x==y);
bool result = (ne == (!e));
result
гарантированно будет true
здесь?
Стандарт C++ определяет операторы равенства в разделе 5.10, но в основном, кажется, определяет их синтаксически (и некоторую семантику в отношении сравнения указателей). Концепция EqualityComparable существует, но нет специального утверждения об отношении ее оператора ==
к оператору !=
.
Существуют соответствующие документы от C++ рабочих групп, в которых говорится, что...
Важно, чтобы равные/неравные [...] вели себя как булевы отрицания друг друга. В конце концов, мир не будет иметь смысла, если оба оператора ==() и оператор! =() Вернули false! Таким образом, эти операторы часто используются в терминах друг друга.
Однако это только отражает Common Sense ™ и не указывает, что они должны быть реализованы таким образом.
Немного предыстории: я просто пытаюсь написать функцию, которая проверяет, равны ли два значения (неизвестного типа), и выводить сообщение об ошибке, если это не так.Я хотел бы сказать, что необходимая концепция здесь заключается в том, что типы являются EqualityComparable
.Но для этого все равно придется писать if (!(x==y)) {...}
и не может писать if (x!=y) {...}
, потому что для этого будет использоваться другой оператор, который вообще не покрывается понятием EqualityComparable
, и который может быть даже перегружен по-другому...
Я знаю, что программист в основном может делать все, что он хочет в своих пользовательских перегрузках. Мне просто интересно, действительно ли ему разрешено делать все, или есть правила, налагаемые стандартом. Может быть, одно из этих тонких утверждений, предполагающих, что отклонение от обычной реализации вызывает неопределенное поведение, подобное тому, которое НатанОливер упомянул в комментарии, но которое, похоже, относится только к определенным типам. Например, в стандарте прямо указано, что для типов контейнеров a!=b
эквивалентно !(a==b)
(раздел 23.2.1, таблица 95, "Требования к контейнерам").
Но для общих пользовательских типов в настоящее время кажется, что таких требований нет. Вопрос помечен как language-lawyer
, потому что я надеялся на определенное утверждение/ссылку, но я знаю, что это может быть почти невозможно: хотя можно указать на раздел, где говорится, что операторы должны быть отрицаниями друг друга, один вряд ли можно доказать, что ни одна из ~ 1500 страниц стандарта не говорит что-то подобное...
Сомневаюсь, и, если не будет дальнейших подсказок, я позже проголосую/приму соответствующие ответы, а пока предположим, что для сравнения неравенства для типов EqualityComparable
нужно сделать, if (!(x==y))
на безопасной стороне.