C++:如果使用自定义 class(不是指针),则 std::map 和 std::set 不会排序

C++: std::map and std::set aren't ordered if using custom class (not pointers)

这一定是非常愚蠢的事情,但我无法从中做出正面或反面的判断。 这是测试代码。

#include <iostream>
#include <vector>
#include <limits>
#include <random>
#include <map>
#include <set>
#include <stdlib.h>
class value_randomized
{
public:
    double value;
    long random;
    value_randomized()
    {
        value=0;
        random=0;
    }
    /*
    bool operator<(const value_randomized& b) const
    {
        if (value<b.value) return true;
        return (random<b.random);
    }
    */
    friend bool operator<(const value_randomized& a, const value_randomized& b);
};
inline bool operator<(const value_randomized& a, const value_randomized& b)
{
    return (a.value<b.value)?true:(a.random<b.random);
}

int main(int argc, char *argv[])
{
    std::map<value_randomized,size_t> results;
    for (size_t i=0; i<1000; ++i)
    {
        value_randomized r;
        r.value=rand();
        r.value/=RAND_MAX;
        r.random=rand();
        results.insert(std::make_pair(r, i));
    }
    std::multiset<value_randomized> s;
    for (size_t i=0; i<1000; ++i)
    {
        value_randomized r;
        r.value=rand();
        r.value/=RAND_MAX;
        r.random=rand();
        s.insert(r);
    }
    return 0;
}

我试过在 class 和 class 之外重载运算符 <。 我已经尝试过地图和(多)集。 但是我不明白结果是如何排序的。 我将展示调试的屏幕 window

调试屏幕1

调试屏幕2

即使直接打印多重集的值也会给出明显无序的结果。这些是第一个结果

(0.0515083,114723506)
(0.0995593,822262754)
(0.0491625,964445884)
(0.410788,11614769)
(0.107848,1389867269)
(0.15123,155789224)
(0.293678,246247255)
(0.331386,195740084)
(0.138238,774044599)
(0.178208,476667372)
(0.162757,588219756)
(0.244327,700108581)
(0.329642,407487131)
(0.363598,619054081)
(0.111276,776532036)
(0.180421,1469262009)
(0.121143,1472713773)
(0.188201,937370163)
(0.210883,1017679567)
(0.301763,1411154259)
(0.394327,1414829150)
(0.383832,1662739668)
(0.260497,1884167637)

显然我遗漏了什么,但是什么?

您的比较函数不满足 strict weak ordering in accordance with the Compare 要求。

可以这样修复现有代码:

inline bool operator<(const value_randomized& a, const value_randomized& b) {
    if(a.value < b.value) return true;
    if(b.value < a.value) return false;
    return a.random < b.random;
}

或更简单,使用std::tie:

inline bool operator<(const value_randomized& a, const value_randomized& b) {
    return std::tie(a.value, a.random) < std::tie(b.value, b.random);
}