Aby obsługiwać typy kluczy zdefiniowane przez użytkownika w programie std::unordered_set<Key>
i std::unordered_map<Key, Value>
należy podać operator==(Key, Key)
funktor skrótu:
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;
Byłoby wygodniej pisać tylko std::unordered_set<X>
z domyślnym hashem dla typu X
, tak jak w przypadku typów dostarczanych wraz z kompilatorem i biblioteką. Po konsultacji
- C ++ Standard Draft N3242 §20.8.12 [unord.hash] i §17.6.3.4 [hash.requirements],
- Wzmocnienie. Nieuporządkowane
- g ++
include\c++\4.7.0\bits\functional_hash.h
- VC10
include\xfunctional
- różne powiązane pytania w Stack Overflow
wydaje się możliwe wyspecjalizowanie 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
}
Biorąc pod uwagę, że obsługa kompilatora dla C ++ 11 jest jeszcze eksperymentalna --- nie próbowałem Clang ---, oto moje pytania:
Czy dodanie takiej specjalizacji do przestrzeni nazw jest legalne
std
? Mam co do tego mieszane uczucia.Która z
std::hash<X>::operator()
wersji, jeśli w ogóle, jest zgodna ze standardem C ++ 11?Czy można to zrobić w sposób przenośny?
std::hash
(w przeciwieństwie do innych rzeczy w std
przestrzeni nazw) jest odradzana w przewodniku stylistycznym Google ; Dodaj szczyptę soli.
operator==(const Key, const Key)