Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/hash"

From cppreference.com
< cpp‎ | utility
(Added to the example)
m (Header list: +<filesystem>.)
 
(46 intermediate revisions by 24 users not shown)
Line 1: Line 1:
{{cpp/title | hash}}
+
{{cpp/title|hash}}
 
{{cpp/utility/hash/navbar}}
 
{{cpp/utility/hash/navbar}}
 +
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | functional}}
+
{{dcl header|bitset}}
{{dcl | since=c++11 | 1=
+
{{dcl header|coroutine}}
 +
{{dcl header|chrono|notes={{mark since c++26}}}}
 +
{{dcl header|filesystem}}
 +
{{dcl header|functional}}
 +
{{dcl header|memory}}
 +
{{dcl header|optional}}
 +
{{dcl header|stacktrace}}
 +
{{dcl header|string}}
 +
{{dcl header|string_view}}
 +
{{dcl header|system_error}}
 +
{{dcl header|thread}}
 +
{{dcl header|typeindex}}
 +
{{dcl header|variant}}
 +
{{dcl header|vector}}
 +
{{dcl|since=c++11|
 
template< class Key >
 
template< class Key >
 
struct hash;
 
struct hash;
Line 9: Line 24:
 
{{dcl end}}
 
{{dcl end}}
  
{{rev begin}}
+
The unordered associative containers {{lc|std::unordered_set}}, {{lc|std::unordered_multiset}}, {{lc|std::unordered_map}}, {{lc|std::unordered_multimap}} use specializations of the template {{tt|std::hash}} as the default hash function.
{{rev|since=c++17|
+
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 {{concept|Hash}}, do not satisfy {{concept|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.
+
}}
+
{{rev end}}
+
  
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 {{concept|Hash}}. In particular, they define an {{c|operator()}} that:
+
Given a type {{tt|Key}}, each specialization {{tt|std::hash<Key>}} is either ''enabled'' or ''disabled''{{sep}}:
 +
* If {{tt|std::hash<Key>}} is not provided by the program or the user, it is disabled.
 +
* Otherwise, {{tt|std::hash<Key>}} is enabled if all following conditions are satisfied:
 +
:* All following requirements are satisfied:
 +
::* {{named req|Hash}} (with {{tt|Key}} as the function call argument type)
 +
::* {{named req|DefaultConstructible}}
 +
::* {{named req|CopyAssignable}}
 +
::* {{named req|Swappable}}
 +
:* Given the following values:
 +
::* {{c|h}}, an object of type {{tt|std::hash<Key>}}.
 +
::* {{c|k1}} and {{c|k2}}, objects of type {{tt|Key}}.
 +
:: All following requirements are satisfied:
 +
::* If {{c|1=k1 == k2}} is {{c|true}}, {{c|1=h(k1) == h(k2)}} is also {{c|true}}.
 +
::* Unless {{tt|std::hash<Key>}} is a [[cpp/language/type#Program-defined type|program-defined specialization]], {{c|h(k1)}} will never throw an exception.
 +
* Otherwise, {{tt|std::hash<Key>}} is disabled.
  
1. Accepts a single parameter of type {{tt|Key}}.
+
Disabled specializations do not satisfy {{named req|Hash}}, do not satisfy {{named req|FunctionObject}}, and following values are all {{c|false}}:
 +
* {{c|std::is_default_constructible<std::hash<Key>>::value}}
 +
* {{c|std::is_copy_constructible<std::hash<Key>>::value}}
 +
* {{c|std::is_move_constructible<std::hash<Key>>::value}}
 +
* {{c|std::is_copy_assignable<std::hash<Key>>::value}}
 +
* {{c|std::is_move_assignable<std::hash<Key>>::value}}
  
2. Returns a value of type {{c|size_t}} that represents the hash value of the parameter.
+
In other words, they exist, but cannot be used.
  
3. Does not throw exceptions when called.
+
{{rrev|until=c++20|
 
+
===Nested types===
4. For two parameters {{tt|k1}} and {{tt|k2}} that are equal, {{c|1=std::hash<Key>()(k1) == std::hash<Key>()(k2)}}.
+
 
+
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<size_t>::max()}}.
+
 
+
All explicit and partial specializations of {{tt|hash}} provided by the standard library are {{concept|DefaultConstructible}}, {{concept|CopyAssignable}}, {{concept|Swappable}} and {{concept|Destructible}}. User-provided specializations of {{tt|hash}} also must meet those requirements.
+
 
+
The unordered associative containers {{lc|std::unordered_set}}, {{lc|std::unordered_multiset}}, {{lc|std::unordered_map}}, {{lc|std::unordered_multimap}} use specializations of the template {{lc|std::hash}} as the default hash function.
+
 
+
===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.
+
 
+
{{rev begin}}
+
{{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 DoS 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.
+
 
+
===Member types===
+
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc hitem | Member type | Definition}}
+
{{dsc hitem|Name|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}}
 +
}}
  
 
===Member functions===
 
===Member functions===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc mem ctor | cpp/utility/hash/hash | constructs a hash function object }}
+
{{dsc mem ctor|cpp/utility/hash/hash|constructs a hash function object}}
{{dsc mem fun | cpp/utility/hash/operator() | calculate the hash of the argument }}
+
{{dsc mem fun|cpp/utility/hash/operator()|calculates the hash of the argument}}
 
{{dsc end}}
 
{{dsc end}}
  
===Standard specializations for basic types===
+
===Standard library specializations===
{{dcl begin}}
+
Each header that declares the template {{tt|std::hash}} also provides enabled specializations of {{tt|std::hash}} for the following types:
{{dcl header | functional}}
+
* all cv-unqualified [[cpp/language/types|arithmetic types]]
{{dcl|
+
* all cv-unqualified [[cpp/language/enum|enumeration types]]
template<> struct hash<bool>;
+
* all cv-unqualified [[cpp/language/pointer|pointer types]]
template<> struct hash<char>;
+
* {{lc|std::nullptr_t}}
template<> struct hash<signed char>;
+
 
template<> struct hash<unsigned char>;
+
On top of that, some headers also provide other enabled {{tt|std::hash}} specializations for library types (see [[#Specializations for library types|below]]).
template<> struct hash<char16_t>;
+
 
template<> struct hash<char32_t>;
+
{{rrev|since=c++17|<!-- P0599R1, not a DR in P0636R2 -->
template<> struct hash<wchar_t>;
+
For all {{tt|std::hash}} specializations provided by the standard library except the following, all their member functions are {{c/core|noexcept}}:
template<> struct hash<short>;
+
* {{ltt|cpp/utility/optional/hash|std::hash<std::optional>}}
template<> struct hash<unsigned short>;
+
* {{ltt|cpp/utility/variant/hash|std::hash<std::variant>}}
template<> struct hash<int>;
+
* {{ltt|cpp/memory/unique_ptr/hash|std::hash<std::unique_ptr>}}
template<> struct hash<unsigned int>;
+
{{rrev|since=c++26|
template<> struct hash<long>;
+
* {{ltt|cpp/chrono/duration/hash|std::hash<std::chrono::duration>}}
template<> struct hash<long long>;
+
* {{ltt|cpp/chrono/time_point/hash|std::hash<std::chrono::time_point>}}
template<> struct hash<unsigned long>;
+
* {{ltt|cpp/chrono/zoned_time/hash|std::hash<std::chrono::zoned_time>}}
template<> struct hash<unsigned long long>;
+
template<> struct hash<float>;
+
template<> struct hash<double>;
+
template<> struct hash<long double>;
+
template< class T > struct hash<T*>;}}
+
{{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>}})
+
 
}}
 
}}
{{rev|since=c++17|
 
Each standard library header that declares the template {{tt|std::hash}} 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.
 
 
}}
 
}}
{{rev end}}
 
  
===Standard specializations for library types===
+
===Specializations for library types===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/string/basic_string/dsc hash}}
+
{{dsc inc|cpp/coroutine/coroutine_handle/dsc hash}}
{{dsc inc | cpp/error/error_code/dsc hash}}
+
{{dsc inc|cpp/error/error_code/dsc hash}}
{{dsc inc | cpp/utility/bitset/dsc hash}}
+
{{dsc inc|cpp/error/error_condition/dsc hash}}
{{dsc inc | cpp/memory/unique_ptr/dsc hash}}
+
{{dsc inc|cpp/utility/stacktrace_entry/dsc hash}}
{{dsc inc | cpp/memory/shared_ptr/dsc hash}}
+
{{dsc inc|cpp/utility/basic_stacktrace/dsc hash}}
{{dsc inc | cpp/types/type_index/dsc hash}}
+
{{dsc inc|cpp/utility/optional/dsc hash}}
{{dsc ptclass | cpp/container/vector bool/hash | title=std::hash{{dsc small|<std::vector<bool>>}} | hash support for {{c|std::vector<bool>}} | notes={{mark c++11}} }}
+
{{dsc inc|cpp/utility/variant/dsc hash}}
{{dsc ptclass | cpp/thread/thread/id/hash | title=std::hash{{dsc small|<std::thread::id>}} | hash support for {{lc|std::thread::id}} | notes={{mark c++11}} }}
+
{{dsc ptclass|cpp/utility/variant/monostate#Helper classes|title=std::hash{{dsc small|<std::monostate>}}|notes={{mark c++17}}|hash support for {{lc|std::monostate}}}}
{{dsc inc | cpp/utility/optional/dsc hash}}
+
{{dsc inc|cpp/utility/bitset/dsc hash}}
{{dsc inc | cpp/utility/variant/dsc hash}}
+
{{dsc inc|cpp/memory/unique_ptr/dsc hash}}
{{dsc inc | cpp/string/basic_string_view/dsc hash}}
+
{{dsc inc|cpp/memory/shared_ptr/dsc hash}}
{{dsc inc | cpp/error/error_condition/dsc hash}}
+
{{dsc inc|cpp/types/type_index/dsc hash}}
 +
{{dsc inc|cpp/string/basic_string/dsc hash}}
 +
{{dsc inc|cpp/string/basic_string_view/dsc hash}}
 +
{{dsc ptclass|cpp/container/vector bool/hash|title=std::hash{{dsc small|<std::vector<bool>>}}|hash support for {{ltt|cpp/container/vector bool|std::vector<bool>}}|notes={{mark c++11}}}}
 +
{{dsc inc|cpp/filesystem/path/dsc hash}}
 +
{{dsc inc|cpp/thread/thread/id/dsc hash}}
 +
{{dsc hash|cpp/chrono/duration|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/time_point|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/day|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/month|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/year|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/weekday|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/weekday_indexed|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/weekday_last|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/month_day|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/month_day_last|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/month_weekday|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/month_weekday_last|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/year_month|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/year_month_day|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/year_month_day_last|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/year_month_weekday|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/year_month_weekday_last|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/zoned_time|nested=true|notes={{mark c++26}}}}
 +
{{dsc hash|cpp/chrono/leap_second|nested=true|notes={{mark c++26}}}}
 
{{dsc end}}
 
{{dsc end}}
  
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]
+
===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. {{c/core|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.
 +
 +
Additional specializations for {{lc|std::pair}} and the standard container types, as well as utility functions to compose hashes are available in [https://www.boost.org/doc/libs/release/libs/container_hash/doc/html/hash.html#ref {{tt|boost::hash}}].
  
 
===Example===
 
===Example===
{{example |
+
{{example
| code=
+
|code=
#include <iostream>
+
#include <cstddef>
#include <iomanip>
+
 
#include <functional>
 
#include <functional>
 +
#include <iomanip>
 +
#include <iostream>
 
#include <string>
 
#include <string>
 
#include <unordered_set>
 
#include <unordered_set>
  
struct S {
+
struct S
 +
{
 
     std::string first_name;
 
     std::string first_name;
 
     std::string last_name;
 
     std::string last_name;
 +
    bool operator==(const S&) const = default; // since C++20
 
};
 
};
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:
+
// Before C++20.
 +
// 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
 
struct MyHash
 
{
 
{
     std::size_t operator()(S const& s) const  
+
     std::size_t operator()(const S& s) const noexcept
 
     {
 
     {
 
         std::size_t h1 = std::hash<std::string>{}(s.first_name);
 
         std::size_t h1 = std::hash<std::string>{}(s.first_name);
 
         std::size_t h2 = std::hash<std::string>{}(s.last_name);
 
         std::size_t h2 = std::hash<std::string>{}(s.last_name);
         return h1 ^ (h2 << 1); // or use boost::hash_combine (see Discussion)
+
         return h1 ^ (h2 << 1); // or use boost::hash_combine
 
     }
 
     }
 
};
 
};
  
// custom specialization of std::hash can be injected in namespace std
+
// Custom specialization of std::hash can be injected in namespace std.
namespace std
+
template<>
 +
struct std::hash<S>
 
{
 
{
     template<> struct hash<S>
+
     std::size_t operator()(const S& s) const noexcept
 
     {
 
     {
         typedef S argument_type;
+
         std::size_t h1 = std::hash<std::string>{}(s.first_name);
        typedef std::size_t result_type;
+
        std::size_t h2 = std::hash<std::string>{}(s.last_name);
        result_type operator()(argument_type const& s) const
+
        return h1 ^ (h2 << 1); // or use boost::hash_combine
        {
+
    }
            result_type const h1 ( std::hash<std::string>{}(s.first_name) );
+
};
            result_type const h2 ( std::hash<std::string>{}(s.last_name) );
+
            return h1 ^ (h2 << 1); // or use boost::hash_combine (see Discussion)
+
        }
+
    };
+
}
+
  
 
int main()
 
int main()
 
{
 
{
   
 
 
     std::string str = "Meet the new boss...";
 
     std::string str = "Meet the new boss...";
 
     std::size_t str_hash = std::hash<std::string>{}(str);
 
     std::size_t str_hash = std::hash<std::string>{}(str);
     std::cout << "hash(" << std::quoted(str) << ") = " << str_hash << '\n';
+
     std::cout << "hash(" << std::quoted(str) << ") =\t" << str_hash << '\n';
 
      
 
      
     S obj = { "Hubert", "Farnsworth"};
+
     S obj = {"Hubert", "Farnsworth"};
     // using the standalone function object
+
     // Using the standalone function object.
     std::cout << "hash(" << std::quoted(obj.first_name) << ','
+
     std::cout << "hash(" << std::quoted(obj.first_name) << ", "
              << std::quoted(obj.last_name) << ") = "
+
              << std::quoted(obj.last_name) << ") =\t"
              << MyHash{}(obj) << " (using MyHash)\n                           or "
+
              << MyHash{}(obj) << " (using MyHash) or\n\t\t\t\t"
              << std::hash<S>{}(obj) << " (using std::hash) " << '\n';
+
              << std::hash<S>{}(obj) << " (using injected specialization)\n";
 
+
   
     // custom hash makes it possible to use custom types in unordered containers
+
     // Custom hash makes it possible to use custom types in unordered containers.
     // The example will use the injected std::hash specialization,
+
     // The example will use the injected std::hash<S> specialization above,
     // to use MyHash instead, pass it as a second template argument
+
     // to use MyHash instead, pass it as a second template argument.
     std::unordered_set<S> names = {obj, {"Bender", "Rodriguez"}, {"Leela", "Turanga"} };
+
     std::unordered_set<S> names = {obj, {"Bender", "Rodriguez"}, {"Turanga", "Leela"}<!---->};
     for(auto& s: names)
+
     for (auto const& s: names)
         std::cout << "hash(" << std::quoted(s.first_name) << ", " << std::quoted(s.last_name)
+
         std::cout << std::quoted(s.first_name) << ' '
                  << ") = " << MyHash{}(s) << '\n';
+
                  << std::quoted(s.last_name) << '\n';
 
}
 
}
 
|p=true
 
|p=true
 
|output=
 
|output=
hash("Meet the new boss...") = 1861821886482076440
+
hash("Meet the new boss...") = 10656026664466977650
hash("Hubert","Farnsworth") = 17622465712001802105 (using MyHash)
+
hash("Hubert", "Farnsworth") = 12922914235676820612 (using MyHash) or
                          or 17622465712001802105 (using std::hash)  
+
                                12922914235676820612 (using injected specialization)
"Leela" "Turanga"
+
 
"Bender" "Rodriguez"
 
"Bender" "Rodriguez"
 +
"Turanga" "Leela"
 
"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=2119|std=C++11|before=specializations for extended integer types were missing|after=provided}}
[[ja:cpp/utility/hash]]
+
{{dr list item|wg=lwg|dr=2148|std=C++11|before=specializations for enumerations were missing|after=provided}}
[[pt:cpp/utility/hash]]
+
{{dr list item|wg=lwg|dr=2543|std=C++11|before={{tt|std::hash}} might not be SFINAE-friendly|after=made SFINAE-friendly}}
[[ru:cpp/utility/hash]]
+
{{dr list item|wg=lwg|dr=2817|std=C++11|before=specialization for {{lc|std::nullptr_t}} was missing|after=provided}}
[[zh:cpp/utility/hash]]
+
{{dr list end}}
 +
 
 +
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 08:23, 6 June 2024

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
 
Defined in header <bitset>
Defined in header <coroutine>
Defined in header <chrono>
(since C++26)
Defined in header <filesystem>
Defined in header <functional>
Defined in header <memory>
Defined in header <optional>
Defined in header <stacktrace>
Defined in header <string>
Defined in header <string_view>
Defined in header <system_error>
Defined in header <thread>
Defined in header <typeindex>
Defined in header <variant>
Defined in header <vector>
template< class Key >
struct hash;
(since C++11)

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.

Given a type Key, each specialization std::hash<Key> is either enabled or disabled :

  • If std::hash<Key> is not provided by the program or the user, it is disabled.
  • Otherwise, std::hash<Key> is enabled if all following conditions are satisfied:
  • All following requirements are satisfied:
  • Given the following values:
  • h, an object of type std::hash<Key>.
  • k1 and k2, objects of type Key.
All following requirements are satisfied:
  • Otherwise, std::hash<Key> 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.

Contents

Nested types

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

[edit] Member functions

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

[edit] Standard library specializations

Each header that declares the template std::hash also provides enabled specializations of std::hash for the following types:

On top of that, some headers also provide other enabled std::hash specializations for library types (see below).

For all std::hash specializations provided by the standard library except the following, all their member functions are noexcept:

(since C++26)
(since C++17)

[edit] Specializations for library types

hash support for std::coroutine_handle
(class template specialization) [edit]
hash support for std::error_code
(class template specialization) [edit]
hash support for std::error_condition
(class template specialization) [edit]
hash support for std::stacktrace_entry
(class template specialization) [edit]
hash support for std::basic_stacktrace
(class template specialization) [edit]
hash support for std::optional
(class template specialization) [edit]
hash support for std::variant
(class template specialization) [edit]
hash support for std::monostate
(class template specialization)
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 strings
(class template specialization) [edit]
hash support for string views
(class template specialization) [edit]
hash support for std::vector<bool>
(class template specialization)
hash support for std::filesystem::path
(class template specialization) [edit]
hash support for std::thread::id
(class template specialization) [edit]
hash support for std::chrono::duration
(class template specialization)
hash support for std::chrono::time_point
(class template specialization)
hash support for std::chrono::day
(class template specialization)
hash support for std::chrono::month
(class template specialization)
hash support for std::chrono::year
(class template specialization)
hash support for std::chrono::weekday
(class template specialization)
hash support for std::chrono::weekday_indexed
(class template specialization)
hash support for std::chrono::weekday_last
(class template specialization)
hash support for std::chrono::month_day
(class template specialization)
hash support for std::chrono::month_day_last
(class template specialization)
hash support for std::chrono::month_weekday
(class template specialization)
hash support for std::chrono::month_weekday_last
(class template specialization)
hash support for std::chrono::year_month
(class template specialization)
hash support for std::chrono::year_month_day
(class template specialization)
hash support for std::chrono::year_month_day_last
(class template specialization)
hash support for std::chrono::year_month_weekday
(class template specialization)
hash support for std::chrono::year_month_weekday_last
(class template specialization)
hash support for std::chrono::zoned_time
(class template specialization)
hash support for std::chrono::leap_second
(class template specialization)

[edit] 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.

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

[edit] Example

#include <cstddef>
#include <functional>
#include <iomanip>
#include <iostream>
#include <string>
#include <unordered_set>
 
struct S
{
    std::string first_name;
    std::string last_name;
    bool operator==(const S&) const = default; // since C++20
};
 
// Before C++20.
// 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()(const S& 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
    }
};
 
// Custom specialization of std::hash can be injected in namespace std.
template<>
struct std::hash<S>
{
    std::size_t operator()(const S& 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) << ") =\t" << 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) << ") =\t"
              << MyHash{}(obj) << " (using MyHash) or\n\t\t\t\t"
              << std::hash<S>{}(obj) << " (using injected 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 const& s: names)
        std::cout << std::quoted(s.first_name) << ' '
                  << std::quoted(s.last_name) << '\n';
}

Possible output:

hash("Meet the new boss...") =  10656026664466977650
hash("Hubert", "Farnsworth") =  12922914235676820612 (using MyHash) or
                                12922914235676820612 (using injected specialization)
"Bender" "Rodriguez"
"Turanga" "Leela"
"Hubert" "Farnsworth"

[edit] 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 2119 C++11 specializations for extended integer types were missing provided
LWG 2148 C++11 specializations for enumerations were missing provided
LWG 2543 C++11 std::hash might not be SFINAE-friendly made SFINAE-friendly
LWG 2817 C++11 specialization for std::nullptr_t was missing provided