Per supportare i tipi di chiave definiti dall'utente in std::unordered_set<Key>
e std::unordered_map<Key, Value>
si deve fornire operator==(Key, Key)
un hash funtore:
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;
Sarebbe più conveniente scrivere solo std::unordered_set<X>
con un hash predefinito per il tipo X
, come per i tipi forniti con il compilatore e la libreria. Dopo aver consultato
- C ++ Standard Draft N3242 §20.8.12 [unord.hash] e §17.6.3.4 [hash.requirements],
- Boost.Unordered
- g ++
include\c++\4.7.0\bits\functional_hash.h
- VC10
include\xfunctional
- varie domande correlate in Stack Overflow
sembra possibile specializzarsi 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
}
Dato che il supporto del compilatore per C ++ 11 è ancora sperimentale --- non ho provato Clang ---, queste sono le mie domande:
È legale aggiungere una tale specializzazione allo spazio dei nomi
std
? Ho sentimenti contrastanti al riguardo.Quale delle
std::hash<X>::operator()
versioni, se esiste, è conforme allo standard C ++ 11?C'è un modo portatile per farlo?
std::hash
(a differenza di altre cose nello std
spazio dei nomi) è scoraggiata dalla guida di stile di Google ; prendilo con un granello di sale.
operator==(const Key, const Key)