2016-07-28 7 views
1

Das ursprüngliche Problem ist irgendwie lang, so dass ich es hier vereinfachen.Probleme bei der Verwendung von ungeordneten_set als Schlüssel von unordered_map, in C++

Ich muss eine Gruppe von Strings mit einer relevanten Ganzzahl erstellen, sagen wir eine Trainingsgruppe. Dann muss ich viele Trainingsgruppen erstellen. Ich möchte alle Trainingsgruppen in einem einzigen Container verwalten. Also entschied ich mich, boost :: unordered_map <> zu verwenden, wobei der Schlüssel std :: unordered_set ist. Weil der BOOST Hash-Wert für den C++ - Standardcontainer hat.

Der vereinfachte Code sind wie folgt:

#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; 
} 

Allerdings ist der Code nicht erfolgreich kompilieren. Es gibt viele kryptische Warnungen und einen Fehler. Der Fehler ist wie folgt:

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>   ] 

Ich weiß nicht, wo der Ursprung dieses Fehlers ist und wie es zu lösen. Wenn der Compiler die Hash-Funktion von unordered_set nicht ablegen kann, enthält die Fehlerinformation Wörter wie "Hash" oder "Key". Es sagt jedoch nur etwas über die Typumwandlung aus, die der Hash-Funktion ähnelt. Also, ich fühle mich verwirrt.

Kann jemand einen Rat geben. Ich verwende Visual Studio 2013 unter Windows 8.

PS: wenn ich den Schlüssel unordered_set<string> zu set<string> oder geändert habe, kompiliert das Programm erfolgreich. Aber ich weiß immer noch nicht den Grund und weiß nicht, wie ich das Problem lösen soll, wenn ich fest entschlossen bin, unordered_set<string> als Schlüssel zu verwenden.

+0

warum muss das Set der Schlüssel der Karte sein? –

+1

Für mein wirkliches Problem ist der zweite Teil einer Trainingsgruppe eigentlich ein anderer ungeordneter_Satz <> des selbstdefinierten Typs. In diesem Post verwende ich eine ganze Zahl, um die Frage zu vereinfachen. Im Vergleich zu unordered_set <> des selbstdefinierten Typs ist daher ein unordered_set <> einer Zeichenfolge besser als Schlüssel zu verwenden. Auch kann ich den Schlüssel unordered_set <>, um nur <> oder Vektor <> zu setzen. Das ungeordnete_set <> ist jedoch für zukünftige Manipulationen bequemer und schneller. –

+0

@JohnSmith: Die Verwendung eines 'unordered_set' als Schlüssel ist wirklich nicht sehr schnell, da das Vergleichsprädikat sehr langsam ist. Es kann in der eingestellten Größe quadratisch sein (gerade weil die Sammlung ungeordnet ist). – rici

Antwort

1

Boost tut nicht bieten eine Hash-Funktion für std::unordered_set, die Liste der Hash-Funktionen enthält z. eine für std::set:

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

So können Sie Ihre eigene Hash-Funktion zur Verfügung stellen müssen, was relativ einfach ist, wenn boost::hash_range mit:

#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

Vielen Dank. Ich vermisste, dass BOOST keine Hash-Funktion für std :: unordered_set bietet. Übrigens: Wird std :: unordered_set als Standard-C++ - Container betrachtet? –

+2

Ja, es ist einfach, eine Hash-Funktion für std :: unordered_set bereitzustellen. Eine Hash-Funktion, die funktioniert, ist ein bisschen komplizierter. Warum denkst du, dass Boost keinen bietet? Tipp: Die Seite, die Sie verlinkt haben, sagt warum. –

+0

@JohnSmith: ['std :: unordered_set'] (http://en.cppreference.com/w/cpp/container/unordered_set) ist seit C++ 11 Teil der C++ - Standardbibliothek. – rici

Verwandte Themen