2009-06-29 5 views
6

... 이런키가 사용자 정의 객체 인 stdext :: hash_map을 사용하는 방법은 무엇입니까? STL과 C 형 ++의 hash_map을 사용

class MyKeyObject 
{ 
    std::string str1; 
    std::string str2; 

    bool operator==(...) { this.str1 == that.str1 ... } 
}; 

class MyData 
{ 
    std::string data1; 
    int data2; 
    std::string etcetc; 
}; 

...

MyKeyObject a = MyKeyObject(...); 
MyData b = MyData(...); 

stdext::hash_map <MyKeyObject, MyData> _myDataHashMap; 
_myDataHashMap[ a ] = b; 

나는 오류의 전체 부하를 얻을. 여기에 처음 세 ...

오류 1 오류 C2784은 : ' 표준 : 운영자 < (const를 표준 : _ 트리 < _Traits이> &, const를 표준 : _ 트리 < _Traits> &)를 bool로 '에 대한되지 를 추론 템플릿 인수 수'const를 MyKeyObject 'C'에서 'const를 표준 : _ 트리 < _Traits> &을 : \ 프로그램 파일은 마이크로 소프트 비주얼 스튜디오 8 \ VC의 \는 \ 기능 143

을 포함 \

오류 2 오류 C2784 : 'const를 표준에 대한 템플릿 인수를 추론 할 수 없습니다 :' 는 표준 : 운영자 < (const를 표준 : < _Elem, _Traits을 basic_string, _Alloc이> &, CONST _Elem *)는 bool에 ' : basic_string < _Elem, _Traits, _Alloc> & const를 태스킹 :: MyKeyObject '에서'C : \ 프로그램 파일 \ 마이크로 소프트 비주얼 스튜디오 8 \ VC의 \ \ 기능 (143)

오류 3 오류 C2784을 포함한다 : ' bool std :: operator < (CONST _Elem *, const를 표준 : < _Elem, _Traits을 basic_string, _Alloc는> &) '에 대한 템플릿을 인수를 추론 할 수없는'const를 MyDataObject 'C' 에서 'const를 _Elem의 * : \ 프로그램 파일은 시각적 인 마이크로 소프트 \ 스튜디오 8 \ VC의 \ 내가 int로 같은 간단한 뭔가 키를 설정하면 \ 모두가 잘

143

...

입니다 기능이 포함됩니다.

내가 뭘 잘못하고 있니?! 템플릿을 가지고 뭔가를해야 할 필요가 있을까요?

이와 같은 맞춤 키 개체를 사용하여 데이터에 액세스하는 더 빠른 (빠른) 방법이 있습니까?

+0

'hash_map' 오래된 확장 기능입니다. tr1의'unordered_map' 또는 Boost를 사용하십시오. – GManNickG

답변

2

이 내장 stdext 네임 스페이스 hash_map 유형뿐만 아니라으로 모두 VS2005위한 솔루션입니다 VS 2005 년 나를 위해 일한 다음을 시도하십시오 부스트 unordered_map (선호). 사용하지 않는 것을 삭제하십시오.

#include <boost/unordered_map.hpp> 
#include <hash_map> 

class HashKey 
{ 
public: 
    HashKey(const std::string& key) 
    { 
     _key=key; 
    } 
    HashKey(const char* key) 
    { 
     _key=key; 
    } 

    // for boost and stdext 
    size_t hash() const 
    { 
     // your own hash function here 
     size_t h = 0; 
     std::string::const_iterator p, p_end; 
     for(p = _key.begin(), p_end = _key.end(); p != p_end; ++p) 
     { 
      h = 31 * h + (*p); 
     } 
     return h; 
    } 
    // for boost 
    bool operator==(const HashKey& other) const 
    { 
     return _key == other._key; 
    } 

    std::string _key; 
}; 

// for boost 
namespace boost 
{ 
    template<> 
    class hash<HashKey> 
    { 
    public : 
     std::size_t operator()(const HashKey &mc) const 
     { 
      return mc.hash(); 
     } 
    }; 
} 

// for stdext 
namespace stdext 
{ 
    template<> 
    class hash_compare<HashKey> 
    { 
    public : 
     static const size_t bucket_size = 4; 
     static const size_t min_buckets = 8; 

     size_t operator()(const HashKey &mc) const 
     { 
      return mc.hash(); 
     } 

     bool operator()(const HashKey &mc1, const HashKey &mc2) const 
     { 
      return (mc1._key < mc2._key); 
     } 
    }; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    { 
     stdext::hash_map<HashKey, int> test; 
     test["one"] = 1; 
     test["two"] = 2; 
    } 

    { 
     boost::unordered_map<HashKey, int> test(8); // optional default initial bucket count 8 
     test["one"] = 1; 
     test["two"] = 2; 
    } 

    return 0; 
} 
3

해시 테이블을 사용하려면 해시 함수를 지정해야합니다. MyKeyObject 오브젝트를 취하고 size_t을 리턴하는 함수를 나타내는 함수 오브젝트를 작성해야합니다. 그런 다음 초기 크기에 이어 두 번째 인수로 펑 통과 :

hash_map <MyKeyObject, MyData> _myDataHashMap(initial_size, YourHashFunctor()); 

다른 방법을, 당신은 당신의 유형에 대한 hash<T> 펑의 템플릿 특수화와 같은 해시 함수를 쓸 수 있습니다; 그런 식으로 사용자 정의 해시 함수를 전달할 필요가 없습니다.

왜 이러한 오류가 구체적으로 발생하는지 알 수 없습니다. 아마도 해시 코드 같은 것을 사용하려고합니다.어쨌든 해시 함수 없이는 작동하지 않아야합니다. 해시 함수는 정수 유형 및 문자열에 대해 미리 정의됩니다.

2

< 링크가 제거되었습니다.은 hash_map을 사용하고 사용자 고유의 해시 함수를 만드는 방법을 명확하게 설명합니다.

(편집 :. 제거 링크 이제 스팸 페이지로 점)

+0

더 좋은 방법은 일반 해시 functor 템플릿 클래스의 템플릿 전문화를 사용하는 것입니다. 이 예제는 맵의 초기화에서 펑터 객체를 사용하는 방법을 보여 주지만, 이는 지루하고 성가신 일입니다. – Marius

0

정점 데이터 구조체를 매핑하는 데 사용하고 있습니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string> 
#include <boost/unordered_map.hpp> 



struct VERTEX 
{ 
float x,y,z; 
}; 

typedef boost::unordered_map<std::string, unsigned int> map; 

int main() 
{ 
VERTEX v1,v2,v3; 

v1.x = 5.0; v1.y = 2.0; v1.z = 2.33333336; 
v2.x = 5.0; v2.y = 2.0; v2.z = 2.32333336; 
v3.x = 5.0; v3.y = 2.0; v3.z = 2.33333336; 

unsigned int vertexSize = sizeof(VERTEX); 
char * v1c = new char[vertexSize]; 
char * v2c = new char[vertexSize]; 
char * v3c = new char[vertexSize]; 

memcpy(v1c, &v1, vertexSize);memcpy(v2c, &v2, vertexSize);memcpy(v3c, &v3, vertexSize); 
map mymap; 

std::string aaa(v1c, vertexSize); 
std::string bbb(v2c, vertexSize); 
std::string ccc(v3c, vertexSize); 

mymap[ aaa ] = 1; 
mymap[ bbb ] = 2; 

unsigned int a = mymap[ aaa ]; 
unsigned int b = mymap[ bbb ]; 
unsigned int c = mymap[ ccc ]; 


return 0; 
} 

이것은 사용자 정의 유형을 사용하는 방법에 대한 간단한 예입니다. 난 그냥 구조체의 메모리의 일부를 char *로 복사 한 다음 크기가 두 번째 param 인 문자열을 만듭니다. 크기는 메모리 데이터가 null 문자를 포함 할 수 있기 때문에 중요합니다. 나는 어떤 추가 비교, 해시 함수가 필요하지 않습니다 ...

0

같은 대답을 찾으려고 할 때 나는이 아주 오래된 질문을 보았고, 기존의 대답은별로 도움이되지 않습니다. 요즘 해시 맵을 원한다면 unordered_map을 사용하고, MyKeyObject 클래스를 hash_map의 키로 사용할 수있는 가장 좋은 방법은 클래스의 해시 함수를 정의하고이 해시 함수를 사용하도록 표준 라이브러리에 지시하는 것입니다. 지도. 즉, 항상 해시 함수를 제공하지 않고도지도 템플릿을 인스턴스화 할 수 있습니다.

'Unordered Associative Containers in C++'에있는 wikipedia page은 쉽게 따라 할 수있는 예제를 제공합니다. 저는 약간 숙지하고 사례에 적용했습니다. 처음에 우리는 회원이 방법으로 간단한 해시 함수를 정의 할 것이다 :

#include <functional> 
class MyKeyObject { 
private: 
    std::string str1; 
    std::string str2; 

public: 
    inline size_t hash() const { 
     return std::hash<std::string>()(str1)^std::hash<std::string>()(str2); 
    } 

    inline bool operator==(const MyKeyObject& other) const { 
     return str1 == other.str1 && str2 == other.str2; 
    } 
}; 

해쉬 함수를 만들기 위해, 우리 모두의 해시가 함께 포함 된 개체에 xor. 이는 std::hash 템플릿을 사용하여 수행됩니다. 템플릿은 하위 유형으로 인스턴스화해야합니다. unordered_map에 대한 세 번째 템플릿 매개 변수로 사용할 수 없습니다. const-equals 연산자도 참고하십시오. 이것은 std::hash 템플릿 클래스에 템플릿 특수화를 추가

namespace std { 
    template <> 
    class hash<MyKeyObject> { 
    public: 
     size_t operator()(const MyKeyObject &aMyKeyObject) const { 
      return aMyKeyObject.hash(); 
     } 
    }; 
} 

MyKeyObject에 대한 해시 연산자를 제공한다 :

이제 우리는이 MyKeyObject 값에 사용되는 해시 함수임을 표준 라이브러리 말할 필요 수업. 위키 피 디아 페이지는 객체의 멤버 인 해시 함수를 호출하는 대신 여기에 직접 해시를 정의합니다. 그러나 해시 함수가 비공개 멤버에 액세스해야한다면 작동하지 않습니다.

지금 당신은 너무 같은 unordered_mapMyKeyObject을 사용할 수 있어야합니다 :

std::unordered_map<MyKeyObject, MyData> _myDataHashMap; 

(그 소리/엑스 코드 테스트)

관련 문제