std :: hash를 전문화하는 방법:: operator () 순서가 지정되지 않은 컨테이너의 사용자 정의 유형에 대해?
에 사용자 정의 키 유형을 지원하기 위해 std::unordered_set<Key>
그리고 std::unordered_map<Key, Value>
하나는 제공해야 operator==(Key, Key)
하고 해시 펑터 :
struct X { int id; /* ... */ };
bool operator==(X a, X b) { return a.id == b.id; }
struct MyHash {
size_t operator()(const X& x) const { return std::hash<int>()(x.id); }
};
std::unordered_set<X, MyHash> s;
그냥 쓸 더 편리 할 것 std::unordered_set<X>
로모그래퍼 기본 해시 유형에 대한 X
유형 컴파일러 및 라이브러리와 함께 주셔서처럼. 상담 후
- C ++ 표준 초안 N3242 §20.8.12 [unord.hash] 및 §17.6.3.4 [hash.requirements],
- 부스트.
- g ++
include\c++\4.7.0\bits\functional_hash.h
- VC10
include\xfunctional
- Stack Overflow의 다양한 관련 질문
전문화가 가능한 것 같습니다 std::hash<X>::operator()
.
namespace std { // argh!
template <>
inline size_t
hash<X>::operator()(const X& x) const { return hash<int>()(x.id); } // works for MS VC10, but not for g++
// or
// hash<X>::operator()(X x) const { return hash<int>()(x.id); } // works for g++ 4.7, but not for VC10
}
C ++ 11에 대한 컴파일러 지원이 아직 실험적이라는 점을 감안할 때 --- 나는 Clang을 시도하지 않았습니다 ----, 내 질문은 다음과 같습니다.
이러한 전문화를 네임 스페이스에 추가하는 것이 합법적
std
입니까? 나는 그것에 대해 복잡한 감정을 가지고 있습니다.어떤
std::hash<X>::operator()
버전이있는 경우 C ++ 11 표준을 준수합니까?휴대용 방법이 있습니까?
네임 스페이스 * 에 전문화 를 추가 하는 것이 명시 적으로 허용되고 권장됩니다 std
. 해시 함수를 추가하는 올바른 (기본적으로 유일한) 방법은 다음과 같습니다.
namespace std {
template <> struct hash<Foo>
{
size_t operator()(const Foo & x) const
{
/* your code here, e.g. "return hash<int>()(x.value);" */
}
};
}
(지원을 고려할 수있는 기타 인기있는 전문 분야는 std::less
, std::equal_to
및 std::swap
입니다.)
*) 관련된 유형 중 하나가 사용자 정의 된 한, 나는 가정한다.
내 베팅은 unorder_map / unorder_set / ... 클래스의 Hash 템플릿 인수에 있습니다.
#include <unordered_set>
#include <functional>
struct X
{
int x, y;
std::size_t gethash() const { return (x*39)^y; }
};
typedef std::unordered_set<X, std::size_t(*)(const X&)> Xunset;
typedef std::unordered_set<X, std::function<std::size_t(const X&)> > Xunset2;
int main()
{
auto hashX = [](const X&x) { return x.gethash(); };
Xunset my_set (0, hashX);
Xunset2 my_set2(0, hashX); // if you prefer a more flexible set typedef
}
물론이야
- hashX는 전역 정적 함수일 수 있습니다.
- 두 번째 경우에는 통과 할 수 있습니다.
- the oldfashioned functor object (
struct Xhasher { size_t operator(const X&) const; };
) std::hash<X>()
- any bind expression satisfying the signature -
- the oldfashioned functor object (
@Kerrek SB has covered 1) and 3).
2) Even though g++ and VC10 declare std::hash<T>::operator()
with different signatures, both library implementations are Standard compliant.
The Standard does not specify the members of std::hash<T>
. It just says that each such specialization must satisfy the same "Hash" requirements needed for the second template argument of std::unordered_set
and so on. Namely:
- Hash type
H
is a function object, with at least one argument typeKey
. H
is copy constructible.H
is destructible.- If
h
is an expression of typeH
orconst H
, andk
is an expression of a type convertible to (possiblyconst
)Key
, thenh(k)
is a valid expression with typesize_t
. - If
h
is an expression of typeH
orconst H
, andu
is an lvalue of typeKey
, thenh(u)
is a valid expression with typesize_t
which does not modifyu
.
'program story' 카테고리의 다른 글
슬라이스에서 요소 위치를 찾는 방법은 무엇입니까? (0) | 2020.08.27 |
---|---|
Visual Studio 2012의 '백그라운드 작업 대기'란 무엇입니까? (0) | 2020.08.27 |
자바 스크립트의 다른 배열에 배열 추가 (0) | 2020.08.27 |
iOS 글꼴의 시각적 목록? (0) | 2020.08.27 |
React 컴포넌트에서 HTML 문자열을 실제 HTML로 렌더링 (0) | 2020.08.27 |