Kode berikut tidak berfungsi dengan MSVC++ 2019, tetapi berfungsi pada kompiler 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;
    }
}

Inilah kesalahan pada MSVC:

enter image description here

Saat di GCC, ini menunjukkan output ini:

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

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

Apa yang menyebabkan kesalahan ini, dan bagaimana mendefinisikan operator dengan benar?

0
user963241 28 Mei 2021, 01:37

2 jawaban

Jawaban Terbaik

Pembanding Anda gagal mematuhi aturan untuk pengurutan lemah yang ketat, yaitu katakan adalah mungkin untuk memiliki situasi berikut:

a < b
b < c
a >= c

MSVC jelas telah mendeteksi ini dan mengajukan kegagalan pernyataan.

Untuk memperbaikinya, Anda dapat mengubah komparator Anda sebagai berikut:

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;
}

Atau, lebih ringkas, gunakan std::tie:

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

Saya juga menyingkirkan else yang berlebihan.

3
Paul Sanders 27 Mei 2021, 22:51

Compare::operator() tidak benar. Itu tidak memenuhi kriteria pengurutan lemah yang ketat.

Anda dapat mengubahnya menjadi:

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

Ini dapat disederhanakan lebih lanjut menggunakan std::tie.

bool operator() (const MyData& lhs, const MyData& rhs) const
{
    return std::tie(lhs.keyA, lhs.keyB) < std::tie(rhs.keyA, rhs.keyB);
}
3
R Sahu 27 Mei 2021, 22:50