2016-07-28 42 views
1

原始問題有點長,所以我在這裏簡化它。使用unordered_set作爲unordered_map的關鍵時的問題,在C++中

我需要創建一組字符串與相關的整數,讓我們說一個訓練組。然後,我需要創建許多培訓小組。我想在一個容器中管理所有培訓組。所以我決定使用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的散列函數,則錯誤信息將包含「Hash」或「Key」等單詞。但是,它只是說了類型轉換的一些東西,它看起來與散列函數類似。所以,我感到困惑。

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

PS:當我將密鑰unordered_set<string>更改爲set<string>vector<string>時,程序編譯成功。但是我仍然不知道原因,如果決心以unordered_set<string>爲關鍵,不知道如何解決問題。

+0

你覺得爲什麼一定要設定成爲地圖的關鍵? –

+1

對於我真正的問題,訓練組的第二部分實際上是另一個自定義類型的無序集合。在這篇文章中,我使用整數來簡化問題。因此,與自定義類型的unordered_set <>相比,字符串的unordered_set <>更適合用作Key。 另外,我可以將Key unordered_set <>更改爲<>或vector <>。然而,unordered_set <>對未來的操作更方便和快捷。 –

+0

@JohnSmith:使用'unordered_set'作爲關鍵字確實不是很快,因爲比較謂詞非常慢。它可以在設定的大小上是二次的(正是因爲集合是無序的)。 – rici

回答

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

+0

非常感謝。我錯過了BOOST不提供std :: unordered_set的散列函數。順便說一下,std :: unordered_set被認爲是一個標準的C++容器嗎? –

+2

是的,很容易爲std :: unordered_set提供散列函數。有效的散列函數有點棘手。爲什麼你認爲提升不提供一個?提示:您鏈接的頁面說明了原因。 –

+0

@JohnSmith:['std :: unordered_set'](http://en.cppreference.com/w/cpp/container/unordered_set)是自C++ 11以來的C++標準庫的一部分。 – rici

相關問題