User defined hash in C++

来源:互联网 发布:云计算标准和应用大会 编辑:程序博客网 时间:2024/05/21 06:17
/*Custom hash functionsRef: https://en.wikipedia.org/wiki/Unordered_associative_containers_(C%2B%2B)#Custom_hash_functionshttp://en.cppreference.com/w/cpp/utility/hash*/#include <iostream>#include <string>#include <iomanip>#include <unordered_set>using namespace std;struct S {    string first_name;    string second_name;};bool operator==(const S& lhs, const S& rhs){    return lhs.first_name == rhs.first_name && lhs.second_name == rhs.second_name;}// custom hash can be a standalone function object:struct MyHash {    size_t operator()(S const& s) const    {        size_t h1 = hash<string> { }(s.first_name);        size_t h2 = hash<string> { }(s.second_name);        return h1 ^ (h2 << 1);  // Combine the hash values for h1 and h2    }};// custom specialization of std::hash can be injected in namespace stdnamespace std{    template<> struct hash<S>    {        typedef S argument_type;        typedef size_t result_type;        result_type operator()(argument_type const& S) const        {            result_type const h1(hash<string>{}(S.first_name));            result_type const h2(hash<string>{}(S.second_name));            return h1 ^ (h2 << 1);        }    };}int main(){    string str = "Meet the new boss...";    size_t str_hash = hash<string> { }(str);    cout << "hash(" << quoted(str) << ") = " << str_hash << '\n';    S obj = { "Hubert", "Farnsworth" };    cout << "hash(" << quoted(obj.first_name) << ","        << quoted(obj.second_name) << ") = "        << MyHash { }(obj) << " (using MyHash)\n                           or "        << hash<S>{}(obj) << " (using std::hash)\n";    // custom hash makes it possible to use custom types in unordered containers    // The example will use the injected std::hash specialization,    // to use MyHash instead, pass it as a second template argument    unordered_set<S> names = { obj, {"Bender", "Rodriguze"}, {"Leela", "Turanga"} };    for (auto& s : names)        cout << quoted(s.first_name) << ' ' << quoted(s.second_name) << '\n';}