在C ++中使用unordered_set作为unordered_map的键的问题

时间:2016-07-28 04:42:11

标签: c++ boost hash containers unordered

原始问题有点长,所以我在这里简化它。

我需要创建一组带有相关整数的字符串,让我们说一个培训组。然后我需要创建许多培训组。我想在一个容器中管理所有培训组。所以我决定使用boost :: unordered_map<>密钥是std :: unordered_set。因为,BOOST具有标准C ++容器的哈希值。

简化代码如下:

#include <string>
#include <unordered_set>
#include <utility>
#include<boost/unordered_map.hpp>

using namespace std;

int main()
{
    boost::unordered_map< unordered_set<string>, int> training_groups;
    pair<unordered_set<string>, int> a_training_group;
    training_groups.insert(a_training_group);
    return 0;
}

但是,代码没有成功编译。有许多神秘的警告和错误。错误如下:

1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xhash(30): error C2440: 'type cast' : cannot convert from 'const std::unordered_set<std::string,std::hash<_Kty>,std::equal_to<_Kty>,std::allocator<_Kty>>' to 'size_t'
1>          with
1>          [
1>              _Kty=std::string
1>          ]
1>          No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>          C:\Program Files\boost\boost_1_59_0\boost/functional/hash/extensions.hpp(262) : see reference to function template instantiation 'size_t stdext::hash_value<T>(const _Kty &)' being compiled
1>          with
1>          [
1>              T=std::unordered_set<std::string,std::hash<std::string>,std::equal_to<std::string>,std::allocator<std::string>>
1>  ,            _Kty=std::unordered_set<std::string,std::hash<std::string>,std::equal_to<std::string>,std::allocator<std::string>>
1>          ]

我不知道这个错误的起源在哪里以及如何解决它。如果编译器无法提交unordered_set的哈希函数,则错误信息将包含像&#34; Hash&#34;或&#34; Key&#34;。但是,它只是说了一些类似于哈希函数的类型转换。所以,我感到困惑。

任何人都可以提供一些建议。我在Windows 8上使用Visual Studio 2013。

PS:当我将密钥unordered_set<string>更改为set<string>vector<string>时,程序成功编译。但我仍然不知道原因,如果我决定使用unordered_set<string>作为关键,我也不知道如何解决问题。

1 个答案:

答案 0 :(得分:1)

Boost std::unordered_set提供哈希函数,哈希函数列表包含例如一个用于std::set

http://www.boost.org/doc/libs/1_61_0/doc/html/hash/reference.html#idp6283424-bb

因此,您必须提供自己的哈希函数,使用boost::hash_range时相对容易:

#include <string>
#include <unordered_set>
#include <utility>
#include <boost/functional/hash/hash_fwd.hpp>

namespace boost
{
template <class K, class C, class A>
std::size_t hash_value(const std::unordered_set<K, C, A>& v)
{
    return boost::hash_range(v.begin(), v.end());
}
} // namespace boost

#include <boost/functional/hash.hpp>
#include <boost/unordered_map.hpp>
int main()
{
    boost::unordered_map<std::unordered_set<std::string>, int> training_groups;
    std::pair<std::unordered_set<std::string>, int> a_training_group;
    training_groups.insert(a_training_group);
    return 0;
}

live example