为啥 std::unordered_set 不将 CComBSTR 类型作为键?

Posted

技术标签:

【中文标题】为啥 std::unordered_set 不将 CComBSTR 类型作为键?【英文标题】:Why does std::unordered_set not take CComBSTR type as a key?为什么 std::unordered_set 不将 CComBSTR 类型作为键? 【发布时间】:2019-10-17 07:55:05 【问题描述】:

当我尝试使用std::unordered_set<CComBSTR>(或std::unordered_set<CAdapt<CComBSTR>>)时,出现错误

c:\apps\vs2017pro\vc\tools\msvc\14.16.27023\include\unordered_set(105) : error C2280 : 'std::hash<_Kty>::hash(const std::hash<_Kty> &)' : attempting to reference a deleted function
with
[
    _Kty = ATL::CComBSTR
]

但是std::set&lt;CComBSTR&gt;(或std::set&lt;CAdapt&lt;CComBSTR&gt;&gt;)没问题。我正在使用 Visual Studio 2017。

我要怎么做才能仍然达到 O(1) 的搜索时间复杂度?(当然,我们可以使用自定义哈希函数来实现 O(1) 的搜索时间复杂度。)

下面给出了最小的可重现示例。

#include "atlbase.h" 
#include <unordered_set>
#include <set>

int main()

    //std::unordered_set<CComBSTR> s;    // compile error
    //std::unordered_set<CAdapt<CComBSTR>> s;    // compile error

    //std::set<CComBSTR> s;    // ok
    //std::set<CAdapt<CComBSTR>> s;    // ok

    return 0;

编辑(06/02/2019):

我理解CComBSTR 没有哈希函数的错误,我们可以创建一个自定义的。我想问的是,std::set 有哈希函数但没有std::unordered_set 的设计原因是什么?

【问题讨论】:

what is the design reason for std::set to have a hash function but not std::unordered_set? 其实是反过来的。 std_set 被实现为平衡树,这意味着它的内容本质上是排序的,但插入和访问时间都是 O(NlogN)。 std::unordered_set 实现为哈希表,这意味着这两个操作都是 O(1)。您选择使用哪个取决于您的用例。 【参考方案1】:

这里的问题是编译器不知道如何散列你的密钥。要解决此问题,您需要提供自定义哈希函数:

#include "atlbase.h" 
#include <unordered_set>
#include <set>
#include <string>

struct HashBSTR

    size_t operator () (const CComBSTR &bstr)
    
        return std::hash <std::wstring> () (bstr.m_str);
    
;


int main()

    std::unordered_set <CComBSTR, HashBSTR> s;
    return 0;

【讨论】:

感谢您的回答。我了解错误的含义以及如何解决。请查看我的编辑。

以上是关于为啥 std::unordered_set 不将 CComBSTR 类型作为键?的主要内容,如果未能解决你的问题,请参考以下文章

在 std::unordered_set<const char *> 中找不到转换为 const char * 的 std::string

对于操作计数()。 std::set<void*> 或 std::unordered_set<void*> 哪个更快?

我的班级有一个 toString() 方法,我如何使用它在 std::unordered_set 中进行散列?

g++5 中 std::unordered_set 编译错误的不完整类型,在 clang++ 中编译

在 std::unordered_map 中使用模板键

为啥这些 C++ STL 无序集不被视为相等?