如何拥有 unordered_multimaps 的 unordered_multimap

Posted

技术标签:

【中文标题】如何拥有 unordered_multimaps 的 unordered_multimap【英文标题】:How to have an unordered_multimap of unordered_multimaps 【发布时间】:2019-08-21 10:45:30 【问题描述】:

我正在通过 unordered_multimaps 进行练习,遇到了一个问题,即 unordered_multimap 包含另一个 unordered_multimap。编译器抛出一个错误,说 c++ 标准不提供这种类型的哈希。我想我必须编写一个哈希函数,但我的理解由于我是 STL 新手,因此受到限制。

我已经尝试过向 unordered_multimap 插入一个结构或另一个多重映射,但到目前为止没有运气。

std::unordered_multimap<long,long>m_Map1;
std::unordered_multimap<CString,m_Map1>m_Map2;    //This line throws 
error
//inserting to the map
m_Map1.insert(std::pair<long,long>(10,20));
m_Map2.insert(_T("ABC"),m_Map1);
//also the compiler does not let me create an object for this map
m_Map1 m_ObjMap;    //error here as well

我应该如何实现这一点。我在这里想要实现的是一个人的姓名与他的出生日期和死亡日期相关联。我希望将日期放在一张地图中并将其与名称映射到 m_Map2。

【问题讨论】:

m_Map1 不是类型,而是std::unordered_multimap&lt;long,long&gt; 的一个实例 hende 你会得到一个编译器错误。你可能想要的是std::unordered_multimap&lt;CString,std::unordered_multimap&lt;long,long&gt;&gt;m_Map2; 在你的第二个多图的声明中,你必须写std::unordered_multimap&lt;CString,std::unordered_multimap&lt;long,long&gt;&gt;m_Map2之类的东西,而不是在模板中写你的第一个多图的名称。 另外,最后一行也是错误的,m_Map1 已经是一个对象,所以你不能创建一个新的对象。我认为你在这里搞乱了类型和对象。 你是对的。 C++ 标准没有在非标准 CString 类型上定义散列。尝试使用标准的std::string,忘记所有仅存在于 Microsoftverse 中的非标准类。 你可能想写类似using Map1 = std::unordered_multimap&lt;long, long&gt;; std::unordered_multimap&lt;CString,Map1&gt; m_Map2; 【参考方案1】:

您的问题是std::hash 没有可用于CString 的专业化

将问题归结为最简单的部分,这也不会编译:

std::unordered_multimap<CString , int> m_Map2;    

因为std::unordered_multimap&lt;CString, anything&gt; 要求存在一个提供std::size_t operator()(CString const&amp;) const 的类std::hash&lt;CString&gt;(它还需要实现std::equal_to&lt;CString&gt;,但如果CString 支持operator==,这将自动可用。

您可以创建这样一个类并合法地将其注入到 std 命名空间中:

#include <unordered_map>
#include <boost/functional/hash.hpp>  // for boost::hash_range, see below

// for exposition
struct CString

    const char* data() const;
    std::size_t length() const;

    bool operator==(CString const& other) const;
;

namespace std

    // specialise std::hash for type ::CString
    template<> struct hash<::CString>
    
        std::size_t operator()(CString const& arg) const
        
            std::size_t seed = 0;

            // perform whatever is your hashing function on arg here
            // accumulating the hash into the variable seed
            // in this case, we're doing it in terms of boost::hash_range

            auto first = arg.data();
            auto last = first + arg.length();
            boost::hash_range(seed, first, last);

            return seed;
        
    ;


std::unordered_multimap<CString , int> m_Map2;    

【讨论】:

@RichardHodges..非常感谢,但恐怕我不能在我的地方使用 boost。但是你的回答让我更好地理解了这个问题。 @Somil 很棒。按预期工作。

以上是关于如何拥有 unordered_multimaps 的 unordered_multimap的主要内容,如果未能解决你的问题,请参考以下文章

在 boost::unordered_multimap 中循环遍历 equal_range

保证 std::unordered_multimap 中的键唯一性

对 unordered_multimap 键进行平均的更好方法是啥?

使用 std::generate 的随机 unordered_multimap

在 unordered_multimap 中准确地迭代每个键一次的有效方法

从 unordered_multimap 中调用另一个类的函数?