I'm learning about operator overloading in C++, and I see that == and != are simply some special functions which can be customized for user-defined types. My concern is, though, why are there two separate definitions needed? I thought that if a == b is true, then a != b is automatically false, and vice versa, and there is no other possibility, because, by definition, a != b is !(a == b). And I couldn't imagine any situation in which this wasn't true. But perhaps my imagination is limited or I am ignorant of something?

我知道我可以用一个定义另一个,但这不是我要问的。我也没有问通过值和单位来比较对象之间的区别。或者两个对象是否可以同时相等和不相等(这绝对不是一个选项!这些事情是相互排斥的)。我想问的是:

有没有可能在这种情况下,问两个对象是否相等的问题是有意义的,但问它们不相等的问题是没有意义的?(无论是从用户的角度,还是从实现者的角度)

如果没有这种可能性,那么究竟为什么c++将这两个操作符定义为两个不同的函数呢?


当前回答

也许是一个不可比较的规则,其中a != b为假,a == b为假,就像一个无状态位。

if( !(a == b || a != b) ){
    // Stateless
}

其他回答

有没有可能的情况是问关于二的问题 对象相等是有意义的,但是问它们不相等 相等没有意义吗?(无论是从用户的角度,还是从 实现者的角度)

这只是个人观点。也许不是。但是语言的设计者并不是无所不知的,他们决定不限制那些可能想出有意义的情况的人(至少对他们来说)。

有一些非常完善的约定,其中(a == b)和(a != b)都是假的,不一定是相反的。特别地,在SQL中,任何与NULL的比较都会产生NULL,而不是true或false。

如果可能的话,创建这样的新示例可能不是一个好主意,因为这太不直观了,但是如果您试图对现有的约定建模,那么可以选择使您的操作符在该上下文中表现得“正确”。

(. .为什么需要两个不同的定义?

需要考虑的一件事是,实现其中一个操作符可能比仅使用另一个操作符的反求值更有效。

(我这里的例子是垃圾,但重点仍然成立,想想bloom过滤器,例如:它们允许快速测试,如果某些东西不在集合中,但测试它是否在集合中可能需要更多时间。)

(. .根据定义,a != b是!(a == b)。

这是你作为程序员的责任。这可能是编写测试的好方法。

如果==和!=操作符实际上并不意味着相等,就像<<和>>流操作符并不意味着位移位一样。如果你把这些符号当作其他概念来对待,它们就不必相互排斥。

就相等而言,如果您的用例保证将对象视为不可比较的,那么每次比较都应该返回false(或者如果操作符返回非bool类型,则返回不可比较的结果类型),那么这样做是有意义的。我想不出一个具体的情况,这将是必要的,但我可以看到它是足够合理的。

当a == b返回bool类型以外的值时,您不会希望语言自动将a != b重写为!(a == b)。有几个原因可以让它这样做。

您可能有表达式构建器对象,其中a == b不会也不打算执行任何比较,而只是构建一些表示a == b的表达式节点。

你可能有惰性求值,其中a == b不会也不打算直接执行任何比较,而是返回某种惰性<bool>,可以在以后的某个时间隐式或显式地转换为bool来实际执行比较。可能与表达式构建器对象结合使用,以便在求值之前完成表达式优化。

你可能有一些自定义的可选<T>模板类,其中给定可选变量T和u,你想允许T == u,但让它返回可选<bool>。

可能还有我没想到的事。即使在这些例子中,操作a == b和a != b都是有意义的,但a != b与!(a == b)不是一回事,因此需要单独的定义。