【发布时间】:2016-06-26 21:28:38
【问题描述】:
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的概念,但没有专门说明其运算符==与!=运算符的关系。
存在related documents from C++ working groups,说的是……
至关重要的是,相等/不等 [...] 表现为彼此的布尔否定。毕竟,如果 operator==() 和 operator!=() 都返回 false,世界将毫无意义!因此,通常根据彼此来实现这些运算符
但是,这仅反映了 Common Sense™,并没有指定它们必须像这样实现。
一些背景知识:我只是想写一个函数来检查两个值(未知类型)是否相等,如果不是这样,则打印一条错误消息。我想说这里需要的概念是类型是EqualityComparable。但是为此,仍然必须写 if (!(x==y)) {…} 并且可以不写 if (x!=y) {…},因为这将使用不同的运算符,而 EqualityComparable 的概念根本没有涵盖这一点,甚至可能以不同的方式重载...
我知道程序员基本上可以在他的自定义重载中为所欲为。我只是想知道他是否真的允许做所有事情,或者是否有标准强加的规则。也许这些微妙的陈述之一表明偏离通常的实现会导致未定义的行为,比如NathanOliver mentioned in a comment, but which seemed to only refer to certain types。例如,标准明确声明对于容器类型,a!=b 等同于!(a==b)(第 23.2.1 节,表 95,“容器要求”)。
但是对于一般的、用户定义的类型,目前似乎没有这样的要求。这个问题被标记为language-lawyer,因为我希望有一个明确的声明/参考,但我知道这几乎是不可能的:虽然有人可以指出它说运营商必须的部分相互否定,很难证明该标准的约 1500 页中没有一个是这样说的……
有疑问,除非有进一步的提示,否则我稍后会支持/接受相应的答案,现在假设比较 EqualityComparable 类型的不相等性应该使用 if (!(x==y)) 来完成安全的一面。
【问题讨论】:
-
我猜你只关心内置类型,因为用户定义的类型可以做任何他们想做的事情。
-
自定义类型可能对两者都有不同的值(由于重载了这些运算符),但它是不好的样式。
-
TL;DR --
operator!=和operator==是留给开发人员实现的两个不同功能,没有什么可以保证对称性 -
顺便说一句,您可以认为这类似于许多标准接口非常谨慎地仅使用
<的方式,以便不要求存在<=、>、>=和是一致的。 -
@DavidSchwartz 我明白了,您的意思可能类似于
NaN,现在答案中也提到了。 (附注:这意味着 STL 实现可能基本上从不使用!=运算符根本,因为它没有被任何概念所涵盖——也许我'将挖掘一些 STL 源,看看是否真的是这样......)
标签: c++ language-lawyer equals-operator