为什么std :: rel_ops需要相等运算符?

时间:2019-02-16 15:27:55

标签: c++ operators std equality

为什么rel_ops需要相等? “ <”还不够吗?

dependencies { classpath 'com.android.tools.build:gradle:3.3.1' classpath 'com.google.gms:google-services:4.1.0' } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:support-media-compat:28.0.0' implementation 'com.android.support:support-vector-drawable:28.0.0' implementation 'com.android.support:support-v4:28.0.0' implementation 'com.android.support:design:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.google.firebase:firebase-auth:16.0.3' implementation 'com.google.firebase:firebase-database:16.0.1' implementation 'com.google.android.gms:play-services-location:16.0.0' implementation 'com.google.android.gms:play-services-maps:16.1.0' }

这可能是一个非常愚蠢的问题。我想念什么吗?

2 个答案:

答案 0 :(得分:2)

  

为什么rel_ops需要相等? “ <”还不够吗?

a==b => !(a<b) && !(b<a)

因为这通常是不正确的。如果rel_ops仅适用于遵循该逻辑的关系运算符,则会受到很大限制。

我想您要记住的是关联容器的<运算符所需的弱排序。来自cppreference

  

标准库在所有使用比较要求的地方,   唯一性是通过使用等价关系确定的。在   不精确的术语,两个对象a和b被认为是等效的(不是   唯一),如果两个比较的值都不小于另一个值:!comp(a,b)&&   !comp(b,a)。

简单地说:仅通过要求! (a < b) && ! (b < a)来确定两个键是否被视为“相同”。因此,您只需要为关联的容器提供<,而无需operator==来确定两个键是否相同。但是,等价(!(a<b)&&!(b<a))不一定等于等价(a==b)。

例如,当您使用此功能

struct my_key {
    int a;
    int b;
    bool operator< (const key_type& other) {
        return a < other.a;   // not comparing b !
    }
};

作为std::map的键,则my_key{1,0}my_key{1,2}是等效的(“相同键”),即使它们不相等。再举一个例子,考虑球形坐标中的Point,当a < ba更接近原点时,我们选择b

struct Point {
    double radius;
    double angle;
    bool operator<(const Point& other) { 
        return radius < other.radius; 
    }
    bool operator==(const Point& other) {
        return (radius == other.radius) && (angle == other.angle);
    }
}

此外,这三个a < bb < aa == b可以同时为假。

还要注意(来自cppreference

  

从C ++ 20开始,不推荐使用std :: rel_ops,而推荐使用运算符<=>。

对于starship operator <=>,您可以选择

std::strong_ordering 
std::weak_ordering
std::partial_ordering
std::strong_equality 
std::weak_equality  

弱排序是必需的,例如std::map(例如my_keyPoint),而强排序的等效性和相等性基本相同。有关更多详细信息和示例,请参考this

答案 1 :(得分:1)

是的,实际上您缺少……。这是非常基本的。它与C ++或编程无关。这是关于数学的。根据数学,只有且仅当“ <”在其操作数域上定义了严格的weak ordering时,您的陈述才是正确的。并非每个用户定义的rel_op的类型都较弱。