【问题标题】:How to use std::string as key of QHash?如何使用 std::string 作为 QHash 的键?
【发布时间】:2020-01-25 14:51:02
【问题描述】:

我想使用std::string 作为QHash 的键:

QHash<std::string, QString> m_hash;
m_hash.insert("ABC", "DEF");

我实现了所需的 qHash:

inline qHash(const std::string& key, uint seed = 0)
{
  qHash(QByteArray::fromRawData(key.data(), key.length()), seed);
}

使用 MSVC 可以正确编译,但 gcc 会生成以下错误:

错误:没有匹配函数调用qHash(const std::__cxx11::basic_string&lt;char&gt;&amp;)

我应该如何解决这个问题?

【问题讨论】:

    标签: c++ qt qhash


    【解决方案1】:

    简答

    • Qt 6.1 及更新版本

    开箱即用支持使用std::string 作为键,因为Qt 现在使用std::hash as a fallback 作为qHash。

    • Qt 6.1 之前的版本

    在std命名空间内定义qHash函数可能会解决编译器错误,但是adding a function to the std namespace is undefined behaviour。所以,这是不允许的。

    一种解决方法是将std::string 包装在帮助类[1] 中:

    class MyHashString : public std::string {};
    QHash<MyHashString, QString> m_hash;
    m_hash.insert("ABC", "DEF");
    
    inline qHash(const MyHashString& key, uint seed = 0)
    {
      qHash(QByteArray::fromRawData(key.data(), key.length()), seed);
    }
    

    长答案

    正如bug report 中所述,必须在std::string 的命名空间内定义qHash 函数:

    这在 C++ 标准中有记录。它称为参数依赖查找。它表示搜索不合格的 qHash(T) 会在 T 的命名空间中找到它。

    因此,所需qHash 的正确定义是:

    namespace std
    {
      inline qHash(const std::string& key, uint seed = 0)
      {
        qHash(QByteArray::fromRawData(key.data(), key.length()), seed);
      }
    }
    

    Qt 文档中也提到过:

    QHash 的键类型除了是可赋值的数据类型之外还有其他要求:它必须提供 operator==(),并且还必须有一个 qHash() 函数在类型的命名空间返回键类型参数的哈希值。

    但是,adding a function to the std namespace is undefined behaviour。因此,使用不理想的解决方法会卡住。

    进一步阅读

    【讨论】:

      猜你喜欢
      • 2011-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 1970-01-01
      • 2012-01-12
      • 2012-10-04
      相关资源
      最近更新 更多