是==和!=相互依赖吗?

我学习了C ++中的运算符重载,并且我发现==!=只是一些可以为用户定义的类型定制的特殊函数。 不过,我担心为什么需要两个单独的定义? 我认为如果a == b是真的,那么a != b自动为false,反之亦然,并且没有其他可能性,因为根据定义, a != b!(a == b) 。 而我无法想象任何情况都不是这样。 但是也许我的想象力有限,或者我对某些东西一无所知?

我知道我可以用另一个来定义一个,但这不是我所问的。 我也没有问及按价值或身份比较对象的区别。 或者两个对象是否可以同时相等和不相等(这绝对不是一种选择!这些东西是相互排斥的)。 我问的是这样的:

有没有什么情况可以提出有关两个物体相同的问题是有道理的,但询问它们不相同是没有意义的? (无论是从用户角度还是从实施者的角度来看)

如果没有这种可能性,那么为什么C ++将这两个运算符定义为两个不同的函数呢?


a == b返回除bool以外的内容时,您不希望语言自动将a != b重写为!(a == b) 。 有几个原因可以让你做到这一点。

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

您可能会有懒惰的评估,其中a == b不会直接执行任何比较,而是会返回某种lazy<bool> ,可以稍后隐式或显式地将其转换为bool ,以便实际上执行比较。 可能与表达式构建器对象结合,以便在评估之前进行完整的表达式优化。

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

我可能还没有想到更多。 即使在这些例子中, a == ba != b这两个操作都有意义,但仍然a != b!(a == b) ,所以需要单独的定义。


如果没有这种可能性,那么为什么C ++将这两个运算符定义为两个不同的函数呢?

因为你可以超载它们,并且通过重载它们,你可以给它们与原来的完全不同的含义。

例如,运算符<<最初是按位左移运算符,现在通常作为插入运算符重载,就像std::cout << something ; 完全不同于原来的意思。

因此,如果您承认运算符的含义在您超载时发生了变化,那么没有理由阻止用户向运算符==赋予含义,这不完全是运算符!=的否定,尽管这可能会造成混淆。


不过,我担心为什么需要两个单独的定义?

你不必定义两者。
如果它们相互排斥,只需定义==<沿着std :: rel_ops即可

Fom cppreference:

#include <iostream>
#include <utility>

struct Foo {
    int n;
};

bool operator==(const Foo& lhs, const Foo& rhs)
{
    return lhs.n == rhs.n;
}

bool operator<(const Foo& lhs, const Foo& rhs)
{
    return lhs.n < rhs.n;
}

int main()
{
    Foo f1 = {1};
    Foo f2 = {2};
    using namespace std::rel_ops;

    //all work as you would expect
    std::cout << "not equal:     : " << (f1 != f2) << 'n';
    std::cout << "greater:       : " << (f1 > f2) << 'n';
    std::cout << "less equal:    : " << (f1 <= f2) << 'n';
    std::cout << "greater equal: : " << (f1 >= f2) << 'n';
}

有没有什么情况可以提出有关两个物体相同的问题是有道理的,但询问它们不相同是没有意义的?

我们经常将这些运营商联系在一起。
尽管这是他们在基本类型上的表现,但没有义务这是他们在自定义数据类型上的行为。 如果你不想要,你甚至不需要返回一个布尔值。

我见过人们以奇怪的方式重载操作符,只是发现它对于其特定于领域的应用程序是有意义的。 即使界面看起来表明它们是相互排斥的,作者也许想要添加特定的内部逻辑。

(无论是从用户角度还是从实施者的角度来看)

我知道你想要一个具体的例子,
所以这里是我认为很实用的Catch测试框架:

template<typename RhsT>
ResultBuilder& operator == ( RhsT const& rhs ) {
    return captureExpression<Internal::IsEqualTo>( rhs );
}

template<typename RhsT>
ResultBuilder& operator != ( RhsT const& rhs ) {
    return captureExpression<Internal::IsNotEqualTo>( rhs );
}

这些操作符做了不同的事情,将一种方法定义为另一种方法是没有意义的。 这样做的原因是,框架可以打印出比较结果。 为了做到这一点,它需要捕捉使用重载操作符的上下文。

链接地址: http://www.djcxy.com/p/27507.html

上一篇: Are == and != mutually dependent?

下一篇: (.1f+.2f==.3f) != (.1f+.2f).Equals(.3f) Why?