等号运算符重载:是(x!= y)==(!(x == y))? [英] Equality operator overloads: Is (x!=y) == (!(x==y))?

查看:207
本文介绍了等号运算符重载:是(x!= y)==(!(x == y))?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++标准是否保证(x!=y)始终具有与!(x==y)相同的真值?

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

我知道这里涉及许多 细微之处:运算符==!=可能会过载.它们可能被重载以具有不同的返回类型(只需将其隐式转换为bool).即使!运算符也可能在返回类型上重载.这就是为什么我手动提及上述真实值"的原因,但尝试进一步加以阐述,利用对bool的隐式转换,并尝试消除可能的歧义:

I know there are many subtleties involved here: The operators == and != may be overloaded. They may be overloaded to have different return types (which only have to be implicitly convertible to bool). Even the !-operator might be overloaded on the return type. That's why I handwavingly referred to the "truth value" above, but trying to elaborate it further, exploiting the implicit conversion to bool, and trying to eliminate possible ambiguities:

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

result是否保证在这里为true?

Is result guaranteed to be true here?

C ++标准在5.10节中指定了等号运算符,但主要似乎是语法上定义它们(以及一些有关指针比较的语义).存在 EqualityComparable concept ,但是存在没有专门说明其运算符==!=运算符之间的关系.

The C++ standard specifies the equality operators in section 5.10, but mainly seems to define them syntactically (and some semantics regarding pointer comparisons). The concept of being EqualityComparable exists, but there is no dedicated statement about the relationship of its operator == to the != operator.

存在与C ++工作相关的相关文档组,说...

There exist related documents from C++ working groups, saying that...

至关重要的是,相等/不相等的行为彼此之间都是布尔求反.毕竟,如果operator ==()和operator!=()都返回false,那么世界将毫无意义!因此,通常要相互实现这些运算符

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™,而没有指定必须这样实施.

However, this only reflects the Common Sense™, and does not specify that they have to be implemented like this.

某些背景:我只是想编写一个函数来检查(未知类型的)两个值是否相等,如果不是这种情况,则会显示一条错误消息.我想说的是,这里需要的概念是类型为EqualityComparable.但是为此,仍然需要编写if (!(x==y)) {...},而可能编写if (x!=y) {...},因为这将使用不同的运算符,而该运算符根本没有涵盖在EqualityComparable的概念中,甚至可能以不同的方式重载...

Some background: I'm just trying to write a function that checks whether two values (of unknown type) are equal, and print an error message if this is not the case. I'd like to say that the required concept here is that the types are EqualityComparable. But for this, one would still have to write if (!(x==y)) {...} and could not write if (x!=y) {...}, because this would use a different operator, which is not covered with the concept of EqualityComparable at all, and which might even be overloaded differently...

我知道程序员基本上 可以在自定义重载中执行他想做的任何事情.我只是想知道他是否真的允许做所有事情,或者该标准是否规定了规则.这些微妙的陈述之一可能暗示偏离常规实现会导致未定义的行为,例如

I know that the programmer basically can do whatever he wants in his custom overloads. I just wondered whether he is really allowed to do everything, or whether there are rules imposed by the standard. Maybe one of these subtle statements that suggest that deviating from the usual implementation causes undefined behavior, like the one that NathanOliver mentioned in a comment, but which seemed to only refer to certain types. For example, the standard explicitly states that for container types, a!=b is equivalent to !(a==b) (section 23.2.1, table 95, "Container requirements").

但是对于一般的用户定义类型,当前似乎没有这样的要求.这个问题被标记为language-lawyer,因为我希望有一个明确的声明/引用,但是我知道这几乎是不可能的:虽然可以指出该部分说运营商必须互相否定,几乎无法证明该标准的约1500页中没有一个说出这样的话...

But for general, user-defined types, it currently seems that there are no such requirements. The question is tagged language-lawyer, because I hoped for a definite statement/reference, but I know that this may nearly be impossible: While one could point out the section where it said that the operators have to be negations of each other, one can hardly prove that none of the ~1500 pages of the standard says something like this...

毫无疑问,除非有进一步的提示,否则我稍后会投票/接受相应的答案,现在假设对于比较EqualityComparable类型的不平等情况,应使用if (!(x==y))进行.安全的一面.

In doubt, and unless there are further hints, I'll upvote/accept the corresponding answers later, and for now assume that for comparing not-equality for EqualityComparable types should be done with if (!(x==y)) to be on the safe side.

推荐答案

C ++标准是否保证(x!=y)始终具有与!(x==y)相同的真值?

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

不,不是.绝对没有什么可以阻止我写作:

No it doesn't. Absolutely nothing stops me from writing:

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

Broken x, y;

那是格式正确的代码.从语义上讲,它已经坏了(顾名思义),但是从纯C ++代码功能的角度来看,它肯定没有错.

That is perfectly well-formed code. Semantically, it's broken (as the name might suggest), but there's certainly nothing wrong from it from a pure C++ code functionality perspective.

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

应用于基本类型(例如,++a ≡ a+=1)的某些预定义运算符之间的标识不必保留于运算符功能.某些预定义的运算符(例如+=)在应用于基本类型时要求操作数为左值.这不是操作员功能所必需的.

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 ++标准中没有任何内容可以保证operator<实际上实现了有效的Ordering(或x<y <==> !(x>=y)等).某些标准库实现实际上会添加工具以尝试在有序容器中为您调试此工具,但这只是实现质量的问题,而不是基于标准的决定.

In the same vein, nothing in the C++ standard guarantees that operator< actually implements a valid Ordering (or that x<y <==> !(x>=y), etc.). Some standard library implementations will actually add instrumentation to attempt to debug this for you in the ordered containers, but that is just a quality of implementation issue and not a standards-compliant-based decision.

Boost.Operators 这样的图书馆解决方案已经存在至少可以使程序员更轻松一点:

Library solutions like Boost.Operators exist to at least make this a little easier on the programmer's side:

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

在C ++ 14中,Fixed不再是基类的集合.但是,在C ++ 17中,它还是一个聚合(通过

In C++14, Fixed is no longer an aggregate with the base class. However, in C++17 it's an aggregate again (by way of P0017).

随着C ++ 20采用 P1185 ,图书馆解决方案实际上已成为一种语言解决方案-您只需要编写以下代码即可:

With the adoption of P1185 for C++20, the library solution has effectively becomes a language solution - you just have to write this:

struct Fixed {
    bool operator==(Fixed const&) const;
};

bool ne(Fixed const& x, Fixed const& y) {
    return x != y;
}

ne()的主体成为计算为!x.operator==(y)的有效表达式-因此,您不必担心保持两个比较一致,也不必依赖库解决方案来提供帮助.

The body of ne() becomes a valid expression that evaluates as !x.operator==(y) -- so you don't have to worry about keeping the two comparison in line nor rely on a library solution to help out.

这篇关于等号运算符重载:是(x!= y)==(!(x == y))?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆