std 映射查找始终为真

std map find is always true

我在使用 std::map 时遇到问题,特别是在使用查找时。 我有以下代码。

class MyClass
{
    update(const QVariant&);
    QVariant m_itemInfo;
    std::map<QVariant, int> m_testMap;
}

void update(const QVariant& itemInfo)
{
    if(m_itemInfo != itemInfo)
    {
         // The items are not equal
         m_itemInfo = itemInfo;
    }
    if(m_testMap.find(itemInfo) == m_testMap.end())
    {
        // TestMap doesnt contain key itemInfo.
        m_testMap.insert(std::make_pair(itemInfo, 1));
    }

    // More code
}

函数 update 在我的代码中被多次调用(使用不同的 itemInfo 对象)。现在当我开始调试它时,我看到第一次调用 update 时,第一个和第二个 if 循环都进入了。到目前为止,一切都很好。但是第二次调用 update 我确实看到调用了第一个 if 循环,但跳过了第二个!我在这里错过了什么?

我猜问题是您传递给 Update 方法的第一个和第二个 QVariant 具有不同的类型(例如,booluint)。 std::map::find 不使用 !=operator 来比较键,它默认使用 operator < (less)。如果两个比较的 QVariant 值具有不同的类型,运算符 != 和 < 可能会相互矛盾。 std::map::find 按以下方式比较键:

Two keys are considered equivalent if the container's comparison object returns false reflexively (i.e., no matter the order in which the elements are passed as arguments).

std::map::find认为v1等于v2

    if(!(v1<v2) && !(v2>v1)) { //is TRUE !!!
    }

要解决您的问题,您应该为 std:map.

定义 less 比较
    class QVariantLessCompare {
        bool operator()(const QVariant&  v1, QVariant& v2) const {
           // ==== You SHOULD IMPLEMENT appropriate comparison here!!! ====
           // Implementation will depend on type of QVariant values you use 
           //return v1 < v2;
       }
    };

并这样使用QVariantCompare

    std::map<QVariant, int, QVariantLessCompare> m_testMap; 

一个更典型的解决方案是使用 QMap,它正确地实现了大多数 QVariant 类型的比较。它不会开箱即用 userTypes(),但这可能仍然适合您的应用程序。

由 Володин Андрей 提出的解决方案的更简洁版本可能如下所示:

struct QVariantLessCompare {
    bool operator()(const QVariant& v1,const QVariant& v2) const 
    {
        return v1.toInt() < v2.toInt();
    }
};