Namespaces
Variants

std:: hash

From cppreference.net
< cpp β€Ž | utility
Utilities library
헀더에 μ •μ˜λ¨ <bitset>
헀더에 μ •μ˜λ¨ <coroutine>
(C++20λΆ€ν„°)
헀더에 μ •μ˜λ¨ <chrono>
(C++26λΆ€ν„°)
헀더에 μ •μ˜λ¨ <filesystem>
(C++17λΆ€ν„°)
헀더에 μ •μ˜λ¨ <functional>
헀더에 μ •μ˜λ¨ <memory>
헀더에 μ •μ˜λ¨ <optional>
(C++17λΆ€ν„°)
헀더에 μ •μ˜λ¨ <stacktrace>
(C++23λΆ€ν„°)
헀더에 μ •μ˜λ¨ <string>
헀더에 μ •μ˜λ¨ <string_view>
(C++17λΆ€ν„°)
헀더에 μ •μ˜λ¨ <system_error>
헀더에 μ •μ˜λ¨ <text_encoding>
(C++26λΆ€ν„°)
헀더에 μ •μ˜λ¨ <thread>
헀더에 μ •μ˜λ¨ <typeindex>
헀더에 μ •μ˜λ¨ <utility>
(C++26λΆ€ν„°)
헀더에 μ •μ˜λ¨ <variant>
(C++17λΆ€ν„°)
헀더에 μ •μ˜λ¨ <vector>
template < class Key >
struct hash ;
(C++11λΆ€ν„°)

hash ν…œν”Œλ¦Ώμ˜ ν™œμ„±ν™”λœ νŠΉμˆ˜ν™”λ“€μ€ ν•΄μ‹œ ν•¨μˆ˜ λ₯Ό κ΅¬ν˜„ν•˜λŠ” ν•¨μˆ˜ 객체λ₯Ό μ •μ˜ν•©λ‹ˆλ‹€.

μ£Όμ–΄μ§„ νƒ€μž… Key 에 λŒ€ν•΄, 각 μ „λ¬Έν™” std::hash<Key> λŠ” ν™œμ„±ν™” λ˜κ±°λ‚˜ λΉ„ν™œμ„±ν™” λ©λ‹ˆλ‹€:

  • λ§Œμ•½ std::hash<Key> κ°€ ν”„λ‘œκ·Έλž¨μ΄λ‚˜ μ‚¬μš©μžμ— μ˜ν•΄ μ œκ³΅λ˜μ§€ μ•ŠμœΌλ©΄, λΉ„ν™œμ„±ν™”λ©λ‹ˆλ‹€.
  • κ·Έλ ‡μ§€ μ•ŠμœΌλ©΄, std::hash<Key> λŠ” λ‹€μŒμ˜ λͺ¨λ“  쑰건이 좩쑱될 λ•Œ ν™œμ„±ν™”λ©λ‹ˆλ‹€:
  • λ‹€μŒ λͺ¨λ“  μš”κ΅¬μ‚¬ν•­μ„ λ§Œμ‘±ν•©λ‹ˆλ‹€:
  • λ‹€μŒ 값듀이 μ£Όμ–΄μ‘Œμ„ λ•Œ:
  • 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 μž…λ‹ˆλ‹€:

**μ°Έκ³ :** 제곡된 HTML λ‚΄μš©μ€ 이미 C++ μ½”λ“œμ™€ κ΄€λ ¨λœ λ‚΄μš©μœΌλ‘œ, λ²ˆμ—­μ΄ ν•„μš”ν•œ 일반 ν…μŠ€νŠΈκ°€ ν¬ν•¨λ˜μ–΄ μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λͺ¨λ“  λ‚΄μš©μ΄ HTML νƒœκ·Έ, C++ μ½”λ“œ, λ˜λŠ” C++ κ΄€λ ¨ μš©μ–΄λ‘œ κ΅¬μ„±λ˜μ–΄ μžˆμ–΄, μ§€μ‹œμ‚¬ν•­μ— 따라 λ²ˆμ—­ν•˜μ§€ μ•Šκ³  원본을 κ·ΈλŒ€λ‘œ μœ μ§€ν–ˆμŠ΅λ‹ˆλ‹€.

λ‹€μ‹œ 말해, 그듀은 μ‘΄μž¬ν•˜μ§€λ§Œ μ‚¬μš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

λͺ©μ°¨

쀑첩 νƒ€μž…

νƒ€μž… μ •μ˜
argument_type (C++17μ—μ„œ μ‚¬μš© 쀑단됨) Key
result_type (C++17μ—μ„œ μ‚¬μš© 쀑단됨) std::size_t
(C++20 이전)

멀버 ν•¨μˆ˜

ν•΄μ‹œ ν•¨μˆ˜ 객체λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€
(public member function)
인자의 ν•΄μ‹œ 값을 κ³„μ‚°ν•©λ‹ˆλ‹€
(public member function)

ν‘œμ€€ 라이브러리 νŠΉμˆ˜ν™”

λ‹€μŒ νƒ€μž…λ“€μ— λŒ€ν•΄ ν™œμ„±ν™”λœ std::hash νŠΉμˆ˜ν™”λ₯Ό μ œκ³΅ν•˜λŠ” 각 ν—€λ”λŠ” std::hash ν…œν”Œλ¦Ώμ„ μ„ μ–Έν•©λ‹ˆλ‹€:

λ…λ¦½ν˜• κ΅¬ν˜„ 은 μ•žμ„œ μ–ΈκΈ‰λœ νŠΉμˆ˜ν™”λ“€κ³Ό 기본적으둜 λΉ„ν™œμ„±ν™”λœ νŠΉμˆ˜ν™”λ“€μ„ μ œκ³΅ν•΄μ•Ό ν•©λ‹ˆλ‹€.

(C++20λΆ€ν„°)

κ²Œλ‹€κ°€, 일뢀 ν—€λ”λŠ” 라이브러리 νƒ€μž…μ— λŒ€ν•΄ λ‹€λ₯Έ ν™œμ„±ν™”λœ std::hash νŠΉμˆ˜ν™”λ„ μ œκ³΅ν•©λ‹ˆλ‹€ (μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜ μ°Έμ‘°).

ν‘œμ€€ λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ œκ³΅ν•˜λŠ” λͺ¨λ“  std::hash νŠΉμˆ˜ν™”μ— λŒ€ν•΄, λ‹€μŒμ„ μ œμ™Έν•œ λͺ¨λ“  멀버 ν•¨μˆ˜λŠ” noexcept μž…λ‹ˆλ‹€:

(C++26λΆ€ν„°)
(C++17λΆ€ν„°)

라이브러리 νƒ€μž…μ— λŒ€ν•œ νŠΉμˆ˜ν™”

μ–Έμ–΄ 지원 라이브러리
std::coroutine_handle 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
진단 라이브러리
std::error_code 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::error_condition 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::type_index 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::stacktrace_entry 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::basic_stacktrace 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
λ©”λͺ¨λ¦¬ 관리 라이브러리
std::unique_ptr 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::shared_ptr 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::indirect 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
λ²”μš© μœ ν‹Έλ¦¬ν‹° 라이브러리
std::optional 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::variant 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::monostate 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::bitset 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
μ»¨ν…Œμ΄λ„ˆ 라이브러리
std::vector<bool> 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
λ¬Έμžμ—΄ 라이브러리
λ¬Έμžμ—΄μ„ μœ„ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
λ¬Έμžμ—΄ 뷰에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
ν…μŠ€νŠΈ 처리 라이브러리
std::text_encoding 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
μ‹œκ°„ 라이브러리
std::chrono::duration 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::chrono::time_point 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::chrono::day 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::chrono::month 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
std::chrono::year 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
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 에 λŒ€ν•œ ν•΄μ‹œ 지원
(클래슀 ν…œν”Œλ¦Ώ νŠΉμˆ˜ν™”)
λ™μ‹œμ„± 지원 라이브러리
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 에 λŒ€ν•œ νŠΉμˆ˜ν™”κ°€ λˆ„λ½λ¨ 제곡됨