【问题标题】:pair<int,int> pair as key of unordered_map issuepair<int,int> 对作为 unordered_map 问题的关键
【发布时间】:2011-06-19 17:13:57
【问题描述】:

我的代码:

 typedef pair<int,int> Pair
  tr1::unordered_map<Pair,bool> h;
  h.insert(make_pair(Pair(0,0),true));

错误

 undefined reference to `std::tr1::hash<std::pair<int, int> >::operator()(std::pair<int, int>) const'

我需要解决什么问题?

谢谢

【问题讨论】:

    标签: c++ unordered-map std-pair


    【解决方案1】:

    发生这种情况是因为 std::tr1::hash&lt;Key&gt; 没有与 Key = std::pair&lt;int, int&gt; 的特化。 在声明 tr1::unordered_map&lt;Pair,bool&gt; h; 之前,您必须使用 Key = std::pair&lt;int, int&gt; 专门化 std::tr1::hash&lt;Key&gt;。 发生这种情况是因为 std 不知道如何散列 pair&lt;int, int&gt;

    下面有一个例子说明如何专门化std::tr1::hash&lt;&gt;

    template <>
    struct std::tr1::hash<std::pair<int, int> > {
    public:
            size_t operator()(std::pair<int, int> x) const throw() {
                 size_t h = SOMETHING;//something with x   
                 return h;
            }
    };
    

    【讨论】:

    • 这很不幸,因为如果我将它专门用于我的库中,而您将其专门用于您的库中,并且我们的定义不相同,那么当我们的库链接在一起时,我们会得到未定义的行为。 std::tr1::hash 有点不够规范,如果可能的话,最好为 unordered_map 指定一个自定义 Hash 类,作为第三个模板参数。
    • 不,你可以在没有任何痛苦的情况下获得相当多的收获,远远超过。
    • @Murilo:如果不疼,那它就不是 C++。
    • @Murilo:当然有可能:template &lt;typename T, U&gt; struct hash&lt;pair&lt;T,U&gt; &gt; { size_t operator() { return hash&lt;T&gt;()(first) ^ hash&lt;U&gt;()(second); }};。这为pair&lt;T,U&gt; 提供了一个有效的哈希码,前提是 T 和 U 的哈希码有效。正如我所说,C++0x 具有用于向量的通用散列,Java 和 Python 也具有用于集合的通用散列。所以我不明白为什么TR1中缺少pair的通用哈希,更不用说C++0x了。
    • 我在 ubuntu 上使用 g++ 4.7.3 进行编译。将代码粘贴到答案中,我得到一个错误: template std::tr1::hash 在不同的命名空间中的专门化。所以我将代码包装在命名空间 std { namespace tr1 //// 代码块 /// } } 中。然后我得到一个错误:非模板 std::tr1 的显式特化
    【解决方案2】:

    Unordered Map 不包含一个对的散列函数,所以如果我们想对一个对进行散列,那么我们必须明确地为它提供一个可以散列一个对的散列函数。

    如果我们想使用 pair 作为 unordered_map 的键,有两种方法:

    1. 为 std::hash 定义专业化
    typedef std::pair<std::string,std::string> pair;
    
    struct pair_hash
    {
        template <class T1, class T2>
        std::size_t operator() (const std::pair<T1, T2> &pair) const
        {
            return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second);
        }
    };
    
    int main()
    {
        std::unordered_map<pair,int,pair_hash> unordered_map =
        {
            {{"C++", "C++11"}, 2011},
            {{"C++", "C++14"}, 2014},
            {{"C++", "C++17"}, 2017},
            {{"Java", "Java 7"}, 2011},
            {{"Java", "Java 8"}, 2014},
            {{"Java", "Java 9"}, 2017}
        };
    
        for (auto const &entry: unordered_map)
        {
            auto key_pair = entry.first;
            std::cout << "{" << key_pair.first << "," << key_pair.second << "}, "
                      << entry.second << '\n';
        }
    
        return 0;
    }
    
    1. 使用 Boost 库 另一个好方法是使用 Boost.functional 中的 boost::hash,它可用于散列整数、浮点数、指针、字符串、数组、对和其他 STL 容器。
    #include <iostream>
    #include <boost/functional/hash.hpp>
    #include <unordered_map>
    #include <utility>
    
    typedef std::pair<std::string,std::string> pair;
    
    int main()
    {
        std::unordered_map<pair,int,boost::hash<pair>> unordered_map =
        {
            {{"C++", "C++11"}, 2011},
            {{"C++", "C++14"}, 2014},
            {{"C++", "C++17"}, 2017},
            {{"Java", "Java 7"}, 2011},
            {{"Java", "Java 8"}, 2014},
            {{"Java", "Java 9"}, 2017}
        };
    
        for (auto const &entry: unordered_map)
        {
            auto key_pair = entry.first;
            std::cout << "{" << key_pair.first << "," << key_pair.second << "}, "
                      << entry.second << '\n';
        }
    
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      遇到了同样的问题:

      unordered_map <pair<x, y>, z> m1;
      

      一些解决方法是:

      unordered_map <stringxy, z> m1;
      // the first and second of the pair merged to a string
      //   though string parsing may be required, looks same complexity overall
      
      unordered_multimap <x, pair<y, z>> m1;
      // second of the pair of the key went into value.  
      //   time complexity slightly increases
      
      deque<deque<x>> d1;
      // here x & y are of same type, z is stored as: d1[x][y] = z
      //   space required is x * y, however time complexity is O(1)
      

      【讨论】:

      • unordered_multimap &lt;x, pair&lt;y, z&gt;&gt; m1; 是否足以插入两对 (x,y) 以使 x 相同而 y 不同?如果 y 在 value 部分,哈希函数怎么知道使用它?
      • 我真的很想帮忙,但是我失去了上述细节的上下文。上面已经给出的 cmets 有帮助吗?
      猜你喜欢
      • 2020-10-22
      • 2021-11-18
      • 2014-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      相关资源
      最近更新 更多