Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/hash"

From cppreference.com
< cpp‎ | utility
(Example for hash specialisation for S had an irrelevant code comment - 'See discussion'. Code was probably copied form stackoverflow.)
(LWG2148, 2291, 2543 (P0513R0))
Line 9: Line 9:
 
{{dcl end}}
 
{{dcl end}}
  
{{rev begin}}
+
Each specialization of this template is either ''enabled'' ("untainted") or ''disabled'' ("poisoned"). For every type {{tt|Key}} for which neither the library nor the user provides an enabled specialization {{tt|std::hash<Key>}}, that specialization exists and is disabled.  Disabled specializations do not satisfy {{named req|Hash}}, do not satisfy {{named req|FunctionObject}}, and following values are all {{c|false}}:
{{rev|since=c++17|
+
* {{c|std::is_default_constructible<std::hash<Key>>::value}}
Each specialization of this template is either ''enabled'' ("untainted") or ''disabled'' ("poisoned"). For every type {{tt|Key}} for which neither the library nor the user provides an enabled specialization {{tt|std::hash<Key>}}, that specialization exists and is disabled.  Disabled specializations do not satisfy {{named req|Hash}}, do not satisfy {{named req|FunctionObject}}, and {{lc|std::is_default_constructible_v}}, {{lc|std::is_copy_constructible_v}}, {{lc|std::is_move_constructible_v}}, {{lc|std::is_copy_assignable_v}}, {{lc|std::is_move_assignable_v}} are all {{c|false}}. In other words, they exist, but cannot be used.
+
* {{c|std::is_copy_constructible<std::hash<Key>>::value}}
}}
+
* {{c|std::is_move_constructible<std::hash<Key>>::value}}
{{rev end}}
+
* {{c|std::is_copy_assignable<std::hash<Key>>::value}}
 
+
* {{c|std::is_move_assignable<std::hash<Key>>::value}}
The {{rev inl|since=c++17|''enabled'' specializations of the}} hash template defines a function object that implements a [[enwiki:Hash function|hash function]].  Instances of this function object satisfy {{named req|Hash}}. In particular, they define an {{c|operator() const}} that:
+
 
+
1. Accepts a single parameter of type {{tt|Key}}.
+
 
+
2. Returns a value of type {{c|std::size_t}} that represents the hash value of the parameter.
+
  
3. Does not throw exceptions when called.
+
In other words, they exist, but cannot be used.
  
4. For two parameters {{tt|k1}} and {{tt|k2}} that are equal, {{c|1=std::hash<Key>()(k1) == std::hash<Key>()(k2)}}.
+
The ''enabled'' specializations of the {{tt|hash}} template defines a function object that implements a [[enwiki:Hash function|hash function]].  Instances of this function object satisfy {{named req|Hash}}. In particular, they define an {{c|operator() const}} that:
  
5. For two different parameters {{tt|k1}} and {{tt|k2}} that are not equal, the probability that {{c|1=std::hash<Key>()(k1) == std::hash<Key>()(k2)}} should be very small, approaching {{c|1=1.0/std::numeric_limits<std::size_t>::max()}}.
+
# Accepts a single parameter of type {{tt|Key}}.
 +
# Returns a value of type {{c|std::size_t}} that represents the hash value of the parameter.
 +
# Does not throw exceptions when called.
 +
# For two parameters {{tt|k1}} and {{tt|k2}} that are equal, {{c|1=std::hash<Key>()(k1) == std::hash<Key>()(k2)}}.
 +
# For two different parameters {{tt|k1}} and {{tt|k2}} that are not equal, the probability that {{c|1=std::hash<Key>()(k1) == std::hash<Key>()(k2)}} should be very small, approaching {{c|1=1.0/std::numeric_limits<std::size_t>::max()}}.
  
 
All explicit and partial specializations of {{tt|hash}} provided by the standard library are {{named req|DefaultConstructible}}, {{named req|CopyAssignable}}, {{named req|Swappable}} and {{named req|Destructible}}. User-provided specializations of {{tt|hash}} also must meet those requirements.
 
All explicit and partial specializations of {{tt|hash}} provided by the standard library are {{named req|DefaultConstructible}}, {{named req|CopyAssignable}}, {{named req|Swappable}} and {{named req|Destructible}}. User-provided specializations of {{tt|hash}} also must meet those requirements.
Line 34: Line 33:
 
The actual hash functions are implementation-dependent and are not required to fulfill any other quality criteria except those specified above. Notably, some implementations use trivial (identity) hash functions which map an integer to itself. In other words, these hash functions are designed to work with unordered associative containers, but not as cryptographic hashes, for example.
 
The actual hash functions are implementation-dependent and are not required to fulfill any other quality criteria except those specified above. Notably, some implementations use trivial (identity) hash functions which map an integer to itself. In other words, these hash functions are designed to work with unordered associative containers, but not as cryptographic hashes, for example.
  
{{rev begin}}
+
Hash functions are only required to produce the same result for the same input within a single execution of a program; this allows salted hashes that prevent collision denial-of-service attacks.
{{rev|since=c++14|Hash functions are only required to produce the same result for the same input within a single execution of a program; this allows salted hashes that prevent collision denial-of-service attacks.}}
+
{{rev end}}
+
  
 
There is no specialization for C strings. {{c|std::hash<const char*>}} produces a hash of the value of the pointer (the memory address), it does not examine the contents of any character array.
 
There is no specialization for C strings. {{c|std::hash<const char*>}} produces a hash of the value of the pointer (the memory address), it does not examine the contents of any character array.
Line 44: Line 41:
 
{{dsc begin}}
 
{{dsc begin}}
 
{{dsc hitem | Member type | Definition}}
 
{{dsc hitem | Member type | Definition}}
{{dsc| {{tt|argument_type}}{{mark|deprecated in C++17}} | {{tt|Key}} }}
+
{{dsc| {{tt|argument_type}}{{mark deprecated c++17}} | {{tt|Key}} }}
{{dsc| {{tt|result_type}}{{mark|deprecated in C++17}} | {{lc|std::size_t}} }}
+
{{dsc| {{tt|result_type}}{{mark deprecated c++17}} | {{lc|std::size_t}} }}
 
{{dsc end}}
 
{{dsc end}}
 
}}
 
}}
Line 81: Line 78:
 
template< class T > struct hash<T*>;}}
 
template< class T > struct hash<T*>;}}
 
{{dcl end}}
 
{{dcl end}}
{{rev begin}}
+
 
{{rev|since=c++14|
+
 
In addition to the above, the standard library provides specializations for all (scoped and unscoped) enumeration types. These may be (but are not required to be) implemented as {{c|std::hash<std::underlying_type<Enum>::type>}})
 
In addition to the above, the standard library provides specializations for all (scoped and unscoped) enumeration types. These may be (but are not required to be) implemented as {{c|std::hash<std::underlying_type<Enum>::type>}})
}}
+
 
{{rev|since=c++17|
+
 
The standard library provides enabled specializations of {{tt|std::hash}} for {{lc|std::nullptr_t}} and all cv-unqualified arithmetic types (including any extended integer types), all enumeration types, and all pointer types.
 
The standard library provides enabled specializations of {{tt|std::hash}} for {{lc|std::nullptr_t}} and all cv-unqualified arithmetic types (including any extended integer types), all enumeration types, and all pointer types.
  
 
Each standard library header that declares the template {{tt|std::hash}} provides all enabled specializations described above. These headers include {{header|string}}, {{header|system_error}}, {{header|bitset}}, {{header|memory}}, {{header|typeindex}}, {{header|vector}}, {{header|thread}}, {{header|optional}}, {{header|variant}}, {{header|string_view}}{{rev inl|since=c++20|, {{header|coroutine}}}}.
 
Each standard library header that declares the template {{tt|std::hash}} provides all enabled specializations described above. These headers include {{header|string}}, {{header|system_error}}, {{header|bitset}}, {{header|memory}}, {{header|typeindex}}, {{header|vector}}, {{header|thread}}, {{header|optional}}, {{header|variant}}, {{header|string_view}}{{rev inl|since=c++20|, {{header|coroutine}}}}.
  
 +
{{rrev|since=c++17|
 
All member functions of all standard library specializations of this template are {{c|noexcept}} except for the member functions of {{ltt|cpp/utility/optional/hash|std::hash<std::optional>}}, {{ltt|cpp/utility/variant/hash|std::hash<std::variant>}}, and {{ltt|cpp/memory/unique_ptr/hash|std::hash<std::unique_ptr>}}
 
All member functions of all standard library specializations of this template are {{c|noexcept}} except for the member functions of {{ltt|cpp/utility/optional/hash|std::hash<std::optional>}}, {{ltt|cpp/utility/variant/hash|std::hash<std::variant>}}, and {{ltt|cpp/memory/unique_ptr/hash|std::hash<std::unique_ptr>}}
 
}}
 
}}
{{rev end}}
 
  
 
===Standard specializations for library types===
 
===Standard specializations for library types===
Line 111: Line 106:
  
 
Note: additional specializations for {{tt|std::pair}} and the standard container types, as well as utility functions to compose hashes are available in [http://www.boost.org/doc/libs/release/doc/html/hash/reference.html boost.hash]
 
Note: additional specializations for {{tt|std::pair}} and the standard container types, as well as utility functions to compose hashes are available in [http://www.boost.org/doc/libs/release/doc/html/hash/reference.html boost.hash]
 
  
 
===Example===
 
===Example===
Line 185: Line 179:
 
"Hubert" "Farnsworth"
 
"Hubert" "Farnsworth"
 
}}
 
}}
[[de:cpp/utility/hash]]
+
 
[[es:cpp/utility/hash]]
+
===Defect reports===
[[fr:cpp/utility/hash]]
+
{{dr list begin}}
[[it:cpp/utility/hash]]
+
{{dr list item|wg=lwg|dr=2148|std=C++11|before=specializations for enumerations were not supported|after=supported}}
[[ja:cpp/utility/hash]]
+
{{dr list item|paper=P0513R0|std=C++11|before={{tt|hash}} might not be SFINAE-friendly|after=made SFINAE-friendly via disabled specializations}}
[[pt:cpp/utility/hash]]
+
{{dr list end}}
[[ru:cpp/utility/hash]]
+
 
[[zh:cpp/utility/hash]]
+
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Revision as of 10:08, 11 July 2020

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
 
Defined in header <functional>
template< class Key >
struct hash;
(since C++11)

Each specialization of this template is either enabled ("untainted") or disabled ("poisoned"). For every type Key for which neither the library nor the user provides an enabled specialization std::hash<Key>, that specialization exists and is disabled. Disabled specializations do not satisfy Hash, do not satisfy FunctionObject, and following values are all false:

In other words, they exist, but cannot be used.

The enabled specializations of the hash template defines a function object that implements a hash function. Instances of this function object satisfy Hash. In particular, they define an operator() const that:

  1. Accepts a single parameter of type Key.
  2. Returns a value of type std::size_t that represents the hash value of the parameter.
  3. Does not throw exceptions when called.
  4. For two parameters k1 and k2 that are equal, std::hash<Key>()(k1) == std::hash<Key>()(k2).
  5. For two different parameters k1 and k2 that are not equal, the probability that std::hash<Key>()(k1) == std::hash<Key>()(k2) should be very small, approaching 1.0/std::numeric_limits<std::size_t>::max().

All explicit and partial specializations of hash provided by the standard library are DefaultConstructible, CopyAssignable, Swappable and Destructible. User-provided specializations of hash also must meet those requirements.

The unordered associative containers std::unordered_set, std::unordered_multiset, std::unordered_map, std::unordered_multimap use specializations of the template std::hash as the default hash function.

Contents

Notes

The actual hash functions are implementation-dependent and are not required to fulfill any other quality criteria except those specified above. Notably, some implementations use trivial (identity) hash functions which map an integer to itself. In other words, these hash functions are designed to work with unordered associative containers, but not as cryptographic hashes, for example.

Hash functions are only required to produce the same result for the same input within a single execution of a program; this allows salted hashes that prevent collision denial-of-service attacks.

There is no specialization for C strings. std::hash<const char*> produces a hash of the value of the pointer (the memory address), it does not examine the contents of any character array.

Member types

Member type Definition
argument_type(deprecated in C++17) Key
result_type(deprecated in C++17) std::size_t
(until C++20)

Member functions

constructs a hash function object
(public member function)
calculate the hash of the argument
(public member function)

Standard specializations for basic types

Defined in header <functional>
template<> struct hash<bool>;

template<> struct hash<char>;
template<> struct hash<signed char>;
template<> struct hash<unsigned char>;
template<> struct hash<char8_t>;        // C++20
template<> struct hash<char16_t>;
template<> struct hash<char32_t>;
template<> struct hash<wchar_t>;
template<> struct hash<short>;
template<> struct hash<unsigned short>;
template<> struct hash<int>;
template<> struct hash<unsigned int>;
template<> struct hash<long>;
template<> struct hash<long long>;
template<> struct hash<unsigned long>;
template<> struct hash<unsigned long long>;
template<> struct hash<float>;
template<> struct hash<double>;
template<> struct hash<long double>;
template<> struct hash<std::nullptr_t>; // C++17

template< class T > struct hash<T*>;

In addition to the above, the standard library provides specializations for all (scoped and unscoped) enumeration types. These may be (but are not required to be) implemented as std::hash<std::underlying_type<Enum>::type>)

The standard library provides enabled specializations of std::hash for std::nullptr_t and all cv-unqualified arithmetic types (including any extended integer types), all enumeration types, and all pointer types.

Each standard library header that declares the template std::hash provides all enabled specializations described above. These headers include <string>, <system_error>, <bitset>, <memory>, <typeindex>, <vector>, <thread>, <optional>, <variant>, <string_view>, <coroutine>(since C++20).

All member functions of all standard library specializations of this template are noexcept except for the member functions of std::hash<std::optional>, std::hash<std::variant>, and std::hash<std::unique_ptr>

(since C++17)

Standard specializations for library types

hash support for strings
(class template specialization) [edit]
hash support for std::error_code
(class template specialization) [edit]
hash support for std::bitset
(class template specialization) [edit]
hash support for std::unique_ptr
(class template specialization) [edit]
hash support for std::shared_ptr
(class template specialization) [edit]
hash support for std::type_index
(class template specialization) [edit]
hash support for std::vector<bool>
(class template specialization)
hash support for std::thread::id
(class template specialization)
hash support for std::optional
(class template specialization) [edit]
hash support for std::variant
(class template specialization) [edit]
hash support for string views
(class template specialization) [edit]
hash support for std::error_condition
(class template specialization) [edit]

Note: additional specializations for std::pair and the standard container types, as well as utility functions to compose hashes are available in boost.hash

Example

#include <iostream>
#include <iomanip>
#include <functional>
#include <string>
#include <unordered_set>
 
struct S {
    std::string first_name;
    std::string last_name;
};
bool operator==(const S& lhs, const S& rhs) {
    return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name;
}
 
// custom hash can be a standalone function object:
struct MyHash
{
    std::size_t operator()(S const& s) const noexcept
    {
        std::size_t h1 = std::hash<std::string>{}(s.first_name);
        std::size_t h2 = std::hash<std::string>{}(s.last_name);
        return h1 ^ (h2 << 1); // or use boost::hash_combine (see Discussion)
    }
};
 
// custom specialization of std::hash can be injected in namespace std
namespace std
{
    template<> struct hash<S>
    {
        std::size_t operator()(S const& s) const noexcept
        {
            std::size_t h1 = std::hash<std::string>{}(s.first_name);
            std::size_t h2 = std::hash<std::string>{}(s.last_name);
            return h1 ^ (h2 << 1); // or use boost::hash_combine
        }
    };
}
 
int main()
{
 
    std::string str = "Meet the new boss...";
    std::size_t str_hash = std::hash<std::string>{}(str);
    std::cout << "hash(" << std::quoted(str) << ") = " << str_hash << '\n';
 
    S obj = { "Hubert", "Farnsworth"};
    // using the standalone function object
    std::cout << "hash(" << std::quoted(obj.first_name) << ',' 
               << std::quoted(obj.last_name) << ") = "
               << MyHash{}(obj) << " (using MyHash)\n                           or "
               << std::hash<S>{}(obj) << " (using injected std::hash<S> specialization)\n";
 
    // custom hash makes it possible to use custom types in unordered containers
    // The example will use the injected std::hash<S> specialization above,
    // to use MyHash instead, pass it as a second template argument
    std::unordered_set<S> names = {obj, {"Bender", "Rodriguez"}, {"Turanga", "Leela"} };
    for(auto& s: names)
        std::cout << std::quoted(s.first_name) << ' ' << std::quoted(s.last_name) << '\n';
}

Possible output:

hash("Meet the new boss...") = 1861821886482076440
hash("Hubert","Farnsworth") = 17622465712001802105 (using MyHash)
                           or 17622465712001802105 (using injected std::hash<S> specialization) 
"Turanga" "Leela"
"Bender" "Rodriguez"
"Hubert" "Farnsworth"

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 2148 C++11 specializations for enumerations were not supported supported
P0513R0 C++11 hash might not be SFINAE-friendly made SFINAE-friendly via disabled specializations