Para admitir tipos de clave definidos por el usuario en std::unordered_set<Key>
y std::unordered_map<Key, Value>
uno tiene que proporcionar operator==(Key, Key)
un functor hash:
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;
Sería más conveniente escribir solo std::unordered_set<X>
con un hash predeterminado para el tipo X
, como para los tipos que vienen junto con el compilador y la biblioteca. Después de consultar
- Borrador de la norma C ++ N3242 §20.8.12 [unord.hash] y §17.6.3.4 [hash.requirements],
- Impulsar sin ordenar
- g ++
include\c++\4.7.0\bits\functional_hash.h
- VC10
include\xfunctional
- varias preguntas relacionadas en Stack Overflow
parece posible especializarse 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
}
Dado que el soporte del compilador para C ++ 11 aún es experimental --- no probé Clang ---, estas son mis preguntas:
¿Es legal agregar tal especialización al espacio de nombres
std
? Tengo sentimientos encontrados respecto de eso.¿Cuál de las
std::hash<X>::operator()
versiones, si alguna, es compatible con el estándar C ++ 11?¿Existe una forma portátil de hacerlo?
std::hash
(a diferencia de otras cosas en el std
espacio de nombres) ; Tómelo con un grano de sal.
operator==(const Key, const Key)