std::hash
| 헤더 <bitset>
|
||
| 에 정의됨 <coroutine>
|
||
| 헤더 <chrono>
|
에 정의됨(C++26부터) |
|
| 헤더 <filesystem>
|
||
| 에 정의됨 <functional>
|
||
| 헤더 <memory>
|
||
| 에 정의됨 <optional>
|
||
| 헤더 <stacktrace>
|
||
| 에 정의됨 <string>
|
||
| 에 정의됨 <system_error>
|
||
| 에 정의됨 <thread>
|
||
| 헤더 <typeindex>
|
||
| 에 정의됨 <variant>
|
||
| 헤더 <vector>
|
||
template< class Key >
struct hash;
|
에 정의됨(C++11부터) | |
비정렬 연관 컨테이너 std::unordered_set, std::unordered_multiset, std::unordered_map, std::unordered_multimap은 템플릿 std::hash의 특수화를 기본 해시 함수로 사용합니다.
타입 Key이 주어지면, 각각의 특수화 std::hash<Key>은 활성화되거나 비활성화 됩니다:
std::hash<Key>이 프로그램이나 사용자에 의해 제공되지 않으면, 비활성화됩니다.- 그렇지 않으면, 다음 모든 조건이 만족될 때
std::hash<Key>이 활성화됩니다:
- 다음 모든 요구 사항이 만족됩니다:
- Hash (함수 호출 인자 타입으로
Key을 사용) - DefaultConstructible
- CopyAssignable
- Swappable
- Hash (함수 호출 인자 타입으로
- 다음 값들이 주어집니다:
h,std::hash<Key>타입의 객체.k1과k2,Key타입의 객체들.
- 다음 모든 요구 사항이 만족됩니다:
- 만약
k1 == k2이true이면,h(k1) == h(k2)도true입니다. std::hash<Key>이 프로그램 정의 특수화가 아니라면,h(k1)은 절대 예외를 던지지 않습니다.
- 만약
- 그렇지 않으면,
std::hash<Key>은 비활성화됩니다.
비활성화된 특수화는 Hash를 만족하지 않으며, FunctionObject를 만족하지 않으며, 다음 값들은 모두 false입니다:
std::is_default_constructible<std::hash<Key>>::valuestd::is_copy_constructible<std::hash<Key>>::valuestd::is_move_constructible<std::hash<Key>>::valuestd::is_copy_assignable<std::hash<Key>>::valuestd::is_move_assignable<std::hash<Key>>::value
다시 말해, 존재하지만 사용될 수 없습니다.
중첩 타입
|
(C++20 이전) |
멤버 함수
|
해시 함수 객체를 생성합니다
(public member function) |
|
|
인자의 해시 값을 계산합니다
(public member function) |
표준 라이브러리 특수화
다음 타입들에 대해 활성화된
std::hash
특수화를 제공하는 각 헤더는
std::hash
템플릿을 선언합니다:
- 모든 cv-unqualified arithmetic types
- 모든 cv-unqualified enumeration types
- 모든 cv-unqualified pointer types
- std::nullptr_t
|
독립형 구현 은 앞서 언급된 특수화들과 기본적으로 비활성화된 특수화들을 제공해야 합니다. |
(C++20부터) |
게다가, 일부 헤더는 라이브러리 타입에 대해 다른 활성화된
std::hash
특수화도 제공합니다
(자세한 내용은
아래
참조).
|
표준 라이브러리가 제공하는 모든
|
(C++17부터) |
라이브러리 타입에 대한 특수화
언어 지원 라이브러리 |
|
|
std::coroutine_handle
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
진단 라이브러리 |
|
|
(C++11)
|
std::error_code
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++17)
|
std::error_condition
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++11)
|
std::type_index
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
std::stacktrace_entry
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::basic_stacktrace
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
메모리 관리 라이브러리 |
|
|
(C++11)
|
std::unique_ptr
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++11)
|
std::shared_ptr
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++26)
|
std::indirect
에 대한 해시 지원
(클래스 템플릿 특수화) |
범용 유틸리티 라이브러리 |
|
|
(C++17)
|
std::optional
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++17)
|
std::variant
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++17)
|
std::monostate
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++11)
|
std::bitset
에 대한 해시 지원
(클래스 템플릿 특수화) |
컨테이너 라이브러리 |
|
|
(C++11)
|
std::vector<bool>
에 대한 해시 지원
(클래스 템플릿 특수화) |
문자열 라이브러리 |
|
|
(C++11)
|
문자열을 위한 해시 지원
(클래스 템플릿 특수화) |
|
(C++17)
(C++17)
(C++20)
(C++17)
(C++17)
|
문자열 뷰에 대한 해시 지원
(클래스 템플릿 특수화) |
텍스트 처리 라이브러리 |
|
|
(C++26)
|
std::text_encoding
에 대한 해시 지원
(클래스 템플릿 특수화) |
시간 라이브러리 |
|
|
std::chrono::duration
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::time_point
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
(C++26)
|
std::chrono::day
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++26)
|
std::chrono::month
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++26)
|
std::chrono::year
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
(C++26)
|
std::chrono::weekday
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
std::chrono::weekday_indexed
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::weekday_last
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::month_day
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::month_day_last
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::month_weekday
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::month_weekday_last
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::year_month
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::year_month_day
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::year_month_day_last
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::year_month_weekday
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::year_month_weekday_last
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::zoned_time
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
|
std::chrono::leap_second
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
입출력 라이브러리 |
|
|
std::filesystem::path
에 대한 해시 지원
(클래스 템플릿 특수화) |
|
동시성 지원 라이브러리 |
|
|
(C++11)
|
std::thread::id
에 대한 해시 지원
(클래스 템플릿 특수화) |
참고 사항
실제 해시 함수는 구현에 따라 다르며 위에서 명시된 기준 외에는 다른 품질 기준을 충족할 의무가 없습니다. 특히 일부 구현에서는 정수를 자기 자신으로 매핑하는 단순한(항등) 해시 함수를 사용합니다. 다시 말해, 이러한 해시 함수는 예를 들어 암호화 해시가 아닌 비정렬 연관 컨테이너와 함께 작동하도록 설계되었습니다.
해시 함수는 프로그램의 단일 실행 내에서 동일한 입력에 대해 동일한 결과를 생성하기만 하면 됩니다. 이를 통해 충돌 기반 서비스 거부 공격을 방지하는 솔트 처리된 해시가 가능해집니다.
C 문자열에 대한 특수화는 존재하지 않습니다. std :: hash < const char * > 는 포인터 값(메모리 주소)의 해시를 생성하며, 문자 배열의 내용을 검사하지 않습니다.
추가적인 특수화들은
std::pair
및 표준 컨테이너 타입들에 대해, 그리고 해시를 구성하기 위한 유틸리티 함수들이
boost::hash
에서 사용 가능합니다.
예제
#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; // C++20부터 }; // C++20 이전 // bool operator==(const S& lhs, const S& rhs) // { // return lhs.first_name == rhs.first_name && lhs.last_name == rhs.last_name; // } // 커스텀 해시는 독립적인 함수 객체일 수 있습니다. 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); // 또는 boost::hash_combine 사용 } }; // std::hash의 커스텀 특수화는 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); // 또는 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"}; // 독립적인 함수 객체 사용 std::cout << "hash(" << std::quoted(obj.first_name) << ", " << std::quoted(obj.last_name) << ") =\t" << MyHash{}(obj) << " (MyHash 사용) 또는\n\t\t\t\t" << std::hash<S>{}(obj) << " (주입된 특수화 사용)\n"; // 커스텀 해시를 사용하면 커스텀 타입을 비정렬 컨테이너에서 사용할 수 있습니다. // 이 예제는 위에서 주입된 std::hash<S> 특수화를 사용하며, // MyHash를 대신 사용하려면 두 번째 템플릿 인자로 전달하십시오. 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'; }
가능한 출력:
hash("Meet the new boss...") = 10656026664466977650
hash("Hubert", "Farnsworth") = 12922914235676820612 (using MyHash) 또는
12922914235676820612 (using injected specialization)
"Bender" "Rodriguez"
"Turanga" "Leela"
"Hubert" "Farnsworth"
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 2119 | C++11 | 확장 정수형에 대한 특수화가 누락됨 | 제공됨 |
| LWG 2148 | C++11 | 열거형에 대한 특수화가 누락됨 | 제공됨 |
| LWG 2543 | C++11 |
std::hash
가 SFINAE-friendly 하지 않을 수 있음
|
SFINAE-friendly 하게 변경됨 |
| LWG 2817 | C++11 | std::nullptr_t 에 대한 특수화가 누락됨 | 제공됨 |