Para oferecer suporte a tipos de chaves definidas pelo usuário em std::unordered_set<Key>
e std::unordered_map<Key, Value>
é necessário fornecer operator==(Key, Key)
um 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;
Seria mais conveniente escrever apenas std::unordered_set<X>
com um hash padrão para o tipo X
, como para os tipos que vêm junto com o compilador e a biblioteca. Depois de consultar
- 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
- várias questões relacionadas no Stack Overflow
parece possível se especializar 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 o suporte do compilador para C ++ 11 ainda é experimental --- eu não tentei o Clang ---, estas são as minhas perguntas:
É legal adicionar essa especialização ao namespace
std
? Tenho sentimentos mistos sobre isso.Qual das
std::hash<X>::operator()
versões, se houver, é compatível com o padrão C ++ 11?Existe uma maneira portátil de fazer isso?
std::hash
(ao contrário de outras coisas no std
namespace) é desencorajada pelo guia de estilo do Google ; tome-o com um grão de sal.
operator==(const Key, const Key)