本文翻译自:Are == and != mutually dependent?
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. 我正在学习C ++中的运算符重载,我发现==
和!=
只是一些特殊的函数,可以为用户定义的类型进行自定义。 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)
. 我认为如果a == b
为真,则a != b
自动为假,反之亦然,并且没有其他可能性,因为根据定义, a != b
是!(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? 但也许我的想象力是有限的,或者我对某些东西一无所知?
I know that I can define one in terms of the other, but this is not what I'm asking about. 我知道我可以用另一个来定义一个,但这不是我要问的。 I'm also not asking about the distinction between comparing objects by value or by identity. 我也没有询问按价值或身份比较对象之间的区别。 Or whether two objects could be equal and non-equal at the same time (this is definitely not an option! these things are mutually exclusive). 或者两个对象是否可以同时相等且不相等(这绝对不是一个选项!这些东西是相互排斥的)。 What I'm asking about is this: 我问的是这个:
Is there any situation possible in which asking questions about two objects being equal does make sense, but asking about them not being equal doesn't make sense? 是否有任何情况可以提出有关两个对象相等的问题是否有意义,但询问它们不相等是没有意义的? (either from the user's perspective, or the implementer's perspective) (无论是从用户的角度,还是从实施者的角度来看)
If there is no such possibility, then why on Earth does C++ have these two operators being defined as two distinct functions? 如果没有这种可能性,那么为什么地球上C ++会将这两个运算符定义为两个不同的函数?
#1楼
参考:https://stackoom.com/question/2YbVR/是-和-相互依赖
#2楼
Is there any situation possible in which asking questions about two objects being equal does make sense, but asking about them not being equal doesn't make sense? 是否有任何情况可以提出有关两个对象相等的问题是否有意义,但询问它们不相等是没有意义的? (either from the user's perspective, or the implementer's perspective) (无论是从用户的角度,还是从实施者的角度来看)
That's an opinion. 这是一个意见。 Maybe it doesn't. 也许它没有。 But the language designers, not being omniscient, decided not to restrict people who might come up with situations in which it might make sense (at least to them). 但语言设计师并非无所不知,他们决定不限制那些可能会提出可能有意义的情况的人(至少对他们而言)。
#3楼
[..] why are there two separate definitions needed? [..]为什么需要两个单独的定义?
One thing to consider is that there might be the possibility of implementing one of these operators more efficiently than just using the negation of the other. 需要考虑的一件事是,可能有可能比仅使用另一个运算符的否定更有效地实现这些运算符之一。
(My example here was rubbish, but the point still stands, think of bloom filters, for example: They allow fast testing if something is not in a set, but testing if it's in may take a lot more time.) (我的例子是垃圾,但问题仍然存在,例如,考虑布隆过滤器:如果某些东西不在一组中,它们允许快速测试,但测试它是否可能需要花费更多时间。)
[..] by definition,
a != b
is!(a == b)
. [...]根据定义,a != b
是!(a == b)
。
And it's your responsibility as programmer to make that hold. 作为程序员,你有责任实现这一目标。 Probably a good thing to write a test for. 编写测试可能是件好事。
#4楼
If the ==
and !=
operators don't actually imply equality, in the same way that the <<
and >>
stream operators don't imply bit-shifting. 如果==
和!=
运算符实际上并不意味着相等,那么<<
和>>
流运算符并不意味着位移。 If you treat the symbols as if they mean some other concept, they don't have to be mutually exclusive. 如果将符号视为某些其他概念,则它们不必相互排斥。
In terms of equality, it could make sense if your use-case warrants treating objects as non-comparable, so that every comparison should return false (or a non-comparable result type, if your operators return non-bool). 在平等方面,如果您的用例保证将对象视为不可比较,则可能有意义,因此每次比较都应返回false(如果您的运算符返回非bool,则返回非可比较的结果类型)。 I can't think of a specific situation where this would be warranted, but I could see it being reasonable enough. 我不能想到这是有必要的具体情况,但我可以看到它足够合理。
#5楼
You would not want the language to automatically rewrite a != b
as !(a == b)
when a == b
returns something other than a bool
. 当a == b
返回除bool
之外的其他内容时,您不希望语言自动将a != b
重写为!(a == b)
。 And there are a few reasons why you might make it do that. 你可以做到这一点有几个原因。
You may have expression builder objects, where a == b
doesn't and isn't intended to perform any comparison, but simply builds some expression node representing a == b
. 您可能有表达式构建器对象,其中a == b
不会,也不打算执行任何比较,而只是构建a == b
表示a == b
表达式节点。
You may have lazy evaluation, where a == b
doesn't and isn't intended to perform any comparison directly, but instead returns some kind of lazy<bool>
that can be converted to bool
implicitly or explicitly at some later time to actually perform the comparison. 你可能有懒惰的评估,其中a == b
没有并且不打算直接执行任何比较,而是返回某种lazy<bool>
,可以在以后隐式或显式地转换为bool
进行比较。 Possibly combined with the expression builder objects to allow complete expression optimisation before evaluation. 可能与表达式构建器对象结合使用,以便在评估之前完成表达式优化。
You may have some custom optional<T>
template class, where given optional variables t
and u
, you want to allow t == u
, but make it return optional<bool>
. 您可能有一些自定义的optional<T>
模板类,其中给定可选变量t
和u
,您希望允许t == u
,但使其返回optional<bool>
。
There's probably more that I didn't think of. 可能还有更多我没想到的。 And even though in these examples the operation a == b
and a != b
do both make sense, still a != b
isn't the same thing as !(a == b)
, so separate definitions are needed. 即使在这些例子中,操作a == b
和a != b
两者都有意义,但仍然a != b
与!(a == b)
,所以需要单独的定义。
#6楼
enum BoolPlus {
kFalse = 0,
kTrue = 1,
kFileNotFound = -1
}
BoolPlus operator==(File& other);
BoolPlus operator!=(File& other);
I can't justify this operator overloading, but in the example above it is impossible to define operator!=
as the "opposite" of operator==
. 我不能证明这个运算符重载是正确的,但在上面的例子中,不可能将operator!=
定义为operator==
的“对立面”。