c – 等式运算符重载:Is(x!= y)==(!(x == y))?

我希望这不是一个重复 – 我搜索关于等式运算符的其他问题,但除了相关问题的一些意见,我没有找到一个明确的语句

tl; dr:

C标准保证(x!= y)总是和!(x == y)有相同的真值吗?

我知道这里有很多细节:运算符==和!=可能是重载的。它们可能被重载以具有不同的返回类型(只需要隐式地转换为bool)。甚至!操作符可能在返回类型上重载。这就是为什么我恳求上面的“真值”,但试图进一步阐述,利用隐式转换为bool,并试图消除可能的歧义:

bool ne = (x!=y);
bool e = (x==y);
bool result = (ne == (!e));

结果保证在这里是真的吗?

C标准在第5.10节中规定了等式运算符,但主要似乎是在句法上定义它们(以及一些关于指针比较的语义)。存在的是EqualityComparable的概念,但是没有关于其operator ==与!=运算符的关系的专用声明。

related documents from C++ working groups,说…

It is vital that equal/unequal […] behave as boolean negations of each other. After all, the world would make no sense if both operator==() and operator!=() returned false! As such, it is common to implement these operators in terms of each other

然而,这仅反映了Common Sense TM,并且没有指定它们必须如此实现。

一些背景:我只是试图写一个函数,检查两个值(未知类型)是否相等,并打印错误消息,如果不是这样。我想说的是,这里需要的概念是类型是EqualityComparable。但是对于这个,仍然必须写if(!(x == y)){…},不能写if(x!= y){…},因为这将使用一个不同的运算符,它没有被EqualityComparable的概念覆盖,甚至可能被不同的重载。

更新

我知道程序员基本上可以在他的自定义重载中做任何他想做的事情。我只是想知道他是否真的被允许做一切,或者是否有标准强加的规则。也许这些微妙的语句之一暗示偏离通常的实现导致未定义的行为,例如NathanOliver mentioned in a comment, but which seemed to only refer to certain types.例如,标准明确说明对于容器类型,!= b等价于!(a == b) (第23.2.1节,表95,“集装箱要求”)。

但对于一般的用户定义类型,目前似乎没有这样的要求。这个问题是标签语言 – 律师,因为我希望有一个明确的声明/参考,但我知道这可能几乎是不可能的:虽然可以指出一节,它说,运算符必须是彼此的否定,一个几乎不能证明标准中的〜1500页都没有这样的说法…

有疑问,除非有进一步的提示,我将upvote /接受相应的答案,现在假设为比较不相等的EqualityComparable类型应该做if(!(x == y))是在安全方面。

Does the C++ standard guarantee that (x!=y) always has the same truth value as !(x==y)?

不,它不。绝对没有阻止我写作:

struct Broken {
    bool operator==(const Broken& ) const { return true; }
    bool operator!=(const Broken& ) const { return true; }
};

Broken x, y;

这是完美良好的代码。语义上,它是破碎的(如名称可能建议),但从纯C代码功能的角度来看,肯定没有错。

标准也清楚地表明这在[over.oper]/7是好的:

The identities among certain predefined operators applied to basic types (for example, ++a ≡ a+=1) need not hold for operator functions. Some predefined operators, such as +=, require an operand to be an lvalue when applied to basic types; this is not required by operator functions.

同样,C标准中没有什么保证,实际上实现有效的排序(或者x boost operators存在,至少使这一点在程序员一方更容易一方:

struct Fixed : equality_comparable<Fixed> {
    bool operator==(const Fixed&) const;
    // a consistent operator!= is provided for you
};

虽然现在Fixed可以不再是一个聚合。所以它仍然不是一个理想的解决方案。虽然P0017显然已被接受为C 17,这将允许列表初始化固定。

http://stackoverflow.com/questions/35943551/equality-operator-overloads-is-x-y-x-y

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c – 等式运算符重载:Is(x!= y)==(!(x == y))?