2012-11-21 3 views
7

처음으로 std::unordered_set을 사용 중이며 해시 함수에 대해 질문이 있습니다. 내가 이해하는 한, 해시 함수를 지정하지 않으면 기본값으로 std :: hash가 사용됩니다. 에 (unordered_set의 해시 함수

error C2440: 'type cast' : cannot convert from 'const MyClass' to 'size_t' 

그것을 변환 함수를 정의 할 필요가있다 :

typedef std::unordered_set<MyClass> USetType; 
USetType mySet; 

내가 구축 할 때, 나는 오류가 발생 :

나는 내 수업 중 하나의 요소인지 구성원이 size_t) unordered_set을 사용자 정의 클래스와 함께 사용하려면? 자신의 해시 함수를 작성하지 않고 기본값을 사용하는 것을 피하는 방법이 있습니까?

+4

: 여기

MyClass 두 개의 문자열 명으로 구성 가정을 사용하는 방법의 예입니다? –

+1

[사용자 지정 해시 함수로 순서가 지정되지 않은 \ _set에 삽입] 가능한 중복 (http://stackoverflow.com/questions/15869066/inserting-into-unordered-set-with-custom-hash-function) –

답변

12

템플릿 인수로 고유 한 해시 함수를 지정하지 않으면 정의하지 않으면 기본값 인 std::hash<MyClass>이 기본값으로 사용됩니다.

namespace std { 
    template <> 
    struct hash<MyClass> 
    { 
    typedef MyClass  argument_type; 
    typedef std::size_t result_type; 

    result_type operator()(const MyClass & t) const 
    { 
     /* ..calculate hash value for t */ 
    } 
    }; 
} 

을 그리고 당신은 전에 해시의 선언을이 코드 을 포함해야합니다 :

베스트 네임 스페이스 std 내부 std::hash의 자신의 전문성을 정의합니다. 이 방법을 사용하면 더 많은 템플릿 인수가 필요하지 않고 단순히 해시를 std::unordered_set<MyClass>으로 선언 할 수 있습니다.

MyClass은 내부에 보이는 내용을 지정하지 않았지만 일반적으로 사용자 정의 유형은 단순히 기본 해시 기능이있는 여러 개의 단순 유형 멤버로 구성됩니다. 이 경우 개별 유형의 해시 값을 전체 조합의 해시 값에 결합해야 할 수 있습니다. Boost 라이브러리는이 목적으로 hash_combine이라는 기능을 제공합니다. 물론 특정 사례 (데이터 값의 분포와 충돌 가능성에 따라 다름)에서 제대로 작동한다는 보장은 없지만 사용하기 쉽고 시작하기 쉬운 출발점을 제공합니다. 사용자 정의 형식의 기본 해시가 될 것으로 기대하는 일

#include <unordered_set> 
#include <boost/functional/hash.hpp> 

struct MyClass 
{ 
    std::string _s1; 
    std::string _s2; 
}; 

namespace std { 
    template <> 
    struct hash<MyClass> 
    { 
    typedef MyClass  argument_type; 
    typedef std::size_t result_type; 

    result_type operator()(const MyClass & t) const 
    { 
     std::size_t val { 0 }; 
     boost::hash_combine(val,t._s1); 
     boost::hash_combine(val,t._s2); 
     return val; 
    } 
    }; 
} 

int main() 
{ 
    std::unordered_set<MyClass> s; 
    /* ... */ 
    return 0; 
} 
+0

특수화를 만드는 대신 MyClass에 대해 std :: hash를 사용하면 멤버에 hash_combine을 사용하는 size_t 변환 멤버 함수를 추가하는 것이 더 쉬워 보입니다. 내 수업은 7-8 개의 기본 유형으로 구성되어 있으며 모두 hash_combine을 호출 한 다음 시드를 반환합니다. – user974967

+0

@ user974967 그게 효과가 있습니까? 단순히 변환 연산자를 추가하면 순서가 지정되지 않은 집합을 얻는 것만으로도 놀랍습니다. 결국, 여전히'std :: hash '을 인스턴스화하려고 시도 할 것이다. – jogojapan

+2

@ user974967 음. 집합을'std :: unordered_set >'으로 선언하면 작동합니다. 이것은 가능한 해결책입니다 만,'operator std :: size_t()'가 정의되어 있어야합니다. 이것은 코드의 다른 부분에서 정수로의 원하지 않는 암시 적 변환을 의미 할 수 있습니다. 이 작업을 권장하지 않습니다. – jogojapan