MSVC C++17 (2019) 上的 Operator() 崩溃程序

Operator() crashing program on MSVC C++17 (2019)

以下代码不适用于 MSVC++ 2019,但适用于 GCC 编译器。

#include <set>
#include <string>
#include <iostream>

struct MyData {

    MyData() {}
    MyData(std::string keyA, std::string keyB) :keyA(keyA), keyB(keyB) {}

    std::string keyA;
    std::string keyB;
};


struct Compare {

    bool operator() (const MyData& lhs, const MyData& rhs) const
    {
        if (lhs.keyA < rhs.keyA)
            return true;

        if (lhs.keyB < rhs.keyB)
            return true;

        else
            // All else conditions would be false
            return false;
    }
};

int main()
{
    std::set<MyData, Compare> s;

    s.insert(MyData("Clark", "Alice"));
    s.insert(MyData("Bob", "Alice"));
    s.insert(MyData("Alice", "Bob"));
    s.insert(MyData("Derek", "Clark"));

    for (auto& i : s)
    {
        std::cout << i.keyA << ", " << i.keyB << std::endl;
    }
}

这是 MSVC 上的错误:

在 GCC 上,它显示以下输出:

Alice, Bob
Bob, Alice
Clark, Alice
Derek, Clark

Process returned 0 (0x0)   execution time : 0.971 s
Press any key to continue.

是什么导致了这个错误,如何正确定义运算符?

您的比较对象不符合strict weak ordering的规则,即可能出现以下情况:

a < b
b < c
a >= c

MSVC 显然已经检测到这一点并引发断言失败。

要解决此问题,您可以按如下方式更改比较器:

bool operator() (const MyData& lhs, const MyData& rhs) const
{
    if (lhs.keyA < rhs.keyA)
        return true;

    if (lhs.keyA == rhs.keyA && lhs.keyB < rhs.keyB)
        return true;

    return false;
}

或者更简洁地使用 std::tie:

bool operator() (const MyData& lhs, const MyData& rhs) const
{
    return std::tie (lhs.keyA, lhs.keyB) < std::tie (rhs.keyA, rhs.keyB);
}

我也去掉了多余的else

Compare::operator() 不正确。不符合strict weak ordering.

的条件

您可以将其更改为:

bool operator() (const MyData& lhs, const MyData& rhs) const
{
    if (lhs.keyA != rhs.keyA)
        return (lhs.keyA < rhs.keyA)
        
    return (lhs.keyB < rhs.keyB);
}

可以使用std::tie进一步简化。

bool operator() (const MyData& lhs, const MyData& rhs) const
{
    return std::tie(lhs.keyA, lhs.keyB) < std::tie(rhs.keyA, rhs.keyB);
}