gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 12:53:41 26 4
gpt4 key购买 nike

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


我知道这里涉及许多微妙之处:运算符 ==!= 可能被重载。它们可能被重载以具有不同的返回类型(只需隐式转换为 bool)。甚至 ! 操作符也可能在返回类型上被重载。这就是为什么我在上面提到了“真值”,但试图进一步阐述它,利用到 bool 的隐式转换,并试图消除可能的歧义:

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

这里是否保证resulttrue

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

存在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

但是,这仅反射(reflect)了 Common Sense™,并没有指定它们必须像这样实现。


一些背景知识:我只是想编写一个函数来检查两个值(未知类型)是否相等,如果不是这样,则打印一条错误消息。我想说这里需要的概念是类型是EqualityComparable。但是为此,仍然需要编写 if (!(x==y)) {…} 并且可以not 编写 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,因为我希望有一个明确的声明/引用,但我知道这几乎是不可能的:虽然有人可以指出它说运算符(operator) 必须相互否定,很难证明该标准的约 1500 页没有一个是这样说的......

有疑问,除非有进一步的提示,否则我稍后会支持/接受相应的答案,现在假设比较 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++ 标准中没有任何内容可以保证 operator<实际上实现了一个有效的 Ordering (或 x<y <==> !(x>=y) 等)。一些标准库实现实际上会添加工具以尝试在有序容器中为您调试它,但这只是实现质量问题,而不是基于标准的决策。


库解决方案,如 Boost.Operators存在至少可以让程序员更容易做到这一点:

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

在 C++14 中,Fixed不再是基类的聚合。但是,在 C++17 中,它又是一个聚合(通过 P0017 的方式)。


通过P1185对于 C++20,库解决方案实际上已成为一种语言解决方案 - 您只需编写以下代码:

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

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

ne() 的正文成为有效表达式,计算结果为 !x.operator==(y) -- 所以你不必担心保持两个比较一致,也不必依赖库解决方案来帮助。

关于c++ - 等式运算符重载 : Is (x! =y) == (!(x==y))?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35943551/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com