Wie spezialisiere ich std :: hash & lt; Key & gt; :: operator () für einen benutzerdefinierten Typ in ungeordneten Containern?
Unterstützt user-defined key types in std::unordered_set<Key>
und std::unordered_map<Key, Value>
man hat operator==(Key, Key)
- und ein hash-Funktor:
struct X { int id; /* ... */ };
bool operator==(X a, X b) { return a.id == b.id; }
struct MyHash {
size_t operator()(const X& x) const { return std::hash<int>()(x.id); }
};
std::unordered_set<X, MyHash> s;
Wäre es bequemer zu schreiben, nur std::unordered_set<X>
mit einem Standard-hash - für Typ X
,
wie für die Arten kommen zusammen mit dem compiler und Bibliothek.
Nach Anhörung
- C++ - Standard Entwurf N3242 §20.8.12 [unord.hash] und §17.6.3.4 [hash.Anforderungen],
- Boost.Ungeordnete
- g++
include\c++\4.7.0\bits\functional_hash.h
- VC10
include\xfunctional
- verschiedenen stellt sich die Frage,s in Stack Overflow
scheint es möglich, sich zu spezialisieren std::hash<X>::operator()
:
namespace std { //argh!
template <>
inline size_t
hash<X>::operator()(const X& x) const { return hash<int>()(x.id); } //works for MS VC10, but not for g++
//or
//hash<X>::operator()(X x) const { return hash<int>()(x.id); } //works for g++ 4.7, but not for VC10
}
Gegeben compiler-Unterstützung für C++11 ist noch experimentellen---ich habe nicht versucht Clang---, dies sind meine Fragen:
- Ist es legal solch eine Spezialisierung namespace
std
? Ich habe gemischte Gefühle darüber. - Welche der
std::hash<X>::operator()
Versionen, wenn überhaupt, ist kompatibel mit standard C++11? - Gibt es eine portable Möglichkeit, es zu tun?
InformationsquelleAutor der Frage René Richter | 2011-11-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sie sind ausdrücklich erlaubt und erwünscht hinzufügen Spezialisierungen namespace
std
*. Die richtige (und im Grunde einzige) Weg, um einen hash-Funktion ist diese:(Andere beliebte Spezialisierungen, die Sie möglicherweise in Betracht zu unterstützen sind
std::less
std::equal_to
undstd::swap
.)*) solange eine der beteiligten Arten ist Benutzer-definiert, nehme ich an.
InformationsquelleAutor der Antwort Kerrek SB
Meine Wette wäre auf die Hash-template-argument für die unordered_map/unorder_set/... Klassen:
Natürlich
struct Xhasher { size_t operator(const X&) const; };
)std::hash<X>()
-
InformationsquelleAutor der Antwort sehe
@Kerrek SB hat unter 1) und 3).
2), obwohl g++ und VC10 erklären
std::hash<T>::operator()
mit unterschiedlichen Signaturen, beide Bibliothek Implementierungen sind Standard-konform.Die der Standard nicht spezifiziert, die Mitglieder der
std::hash<T>
. Es sagt nur, dass jeder solche Spezialisierung erfüllen müssen, die gleichen "Hash" Anforderungen, die für die zweite Vorlage-argument vonstd::unordered_set
und so weiter. Nämlich:H
ist ein function-Objekt, mit mindestens einem argument typeKey
.H
kopieren bebaubar.H
zerstörbar ist.h
ist ein Ausdruck vom TypH
oderconst H
undk
ist ein Ausdruck für eine Art Cabrio zu (eventuellconst
)Key
dannh(k)
ist ein Gültiger Ausdruck mit Typ -size_t
.h
ist ein Ausdruck vom TypH
oderconst H
undu
ist ein lvalue des TypsKey
dannh(u)
ist ein Gültiger Ausdruck mit Typ -size_t
die nicht ändernu
.InformationsquelleAutor der Antwort aschepler