boost :: unordered_map에서 키에 맞춤형 유형을 사용하려면 어떻게해야합니까?
-
11-09-2019 - |
문제
현재 프로젝트에서 Boost의 해시 맵 구현을 사용하고 있으며 키에 대한 사용자 정의 유형을 구현하려고합니다. 키로 사용할 단일 128 비트 데이터 타입으로 결합하려는 4 개의 서명되지 않은 정수가 있습니다.
나는 내 스토리지 역할을하는 4 개의 요소로 구성된 32 비트 정수 배열로 구조물을 만들었습니다. 솔직히 말해서 Boost의 해시 맵이 어떻게 작동하는지 잘 모르겠으므로 여기서 무엇을하고 있는지 잘 모르겠지만 Boost 문서를 따랐습니다 (http://www.boost.org/doc/libs/1_37_0/doc/html/hash/custom.html) boost를 확장하기 위해 :: 해시를 위해, 그리고 해시 함수와 사용자 정의 비교 연산자를 만들었습니다.
이 사용자 지정 유형이 헤더에 정의되어 있습니다. 이것은 내 코드입니다.
#ifndef INT128_H_
#define INT128_H_
// Custom 128-bit datatype used to store and compare the results of a weakened hash operation.
struct int128
{
unsigned int storage[4];
/* Assignment operation that takes a 32-bit integer array of four elements.
This makes assignment of values a shorter and less painful operation. */
void operator=(const unsigned int input[4])
{
for(int i = 0; i < 4; i++)
storage[i] = input[i];
}
};
bool operator==(int128 const &o1, int128 const &o2)
{
if(o1.storage[0] == o2.storage[0] && o1.storage[1] == o2.storage[1] &&
o1.storage[2] == o2.storage[2] && o1.storage[3] == o2.storage[3])
return true;
return false;
}
// Hash function to make int128 work with boost::hash.
std::size_t hash_value(int128 const &input)
{
boost::hash<unsigned long long> hasher;
unsigned long long hashVal = input.storage[0];
for(int i = 1; i < 3; i++)
{
hashVal *= 37;
hashVal += input.storage[1];
}
return hasher(hashVal);
}
#endif
이제 실제로 Boost의 변환되지 않은 맵 에서이 유형을 사용하면 코드가 컴파일되지만 링크되지 않습니다. 링커는 여러 객체 파일에 여러 번 정의 된 기호가 있다고 주장합니다. 이지도에서 128 비트 유형을 작동시키고 싶습니다. 내가 망치고있는 것에 대한 팁, 또는 더 좋은 방법이 있습니까?
해결책
정렬되지 않은 맵의 참여는 당신이 직면 한 문제에 거의 부수적입니다. 실제 문제는 당신이 정의하고 있다는 것입니다 hash_value
그리고 operator==
위의 헤더가 포함 된 모든 파일에서
당신은 이것을 다음 중 하나로 치료할 수 있습니다.
- 두 가지를 인라인 함수로 정의합니다
- 헤더에서 그들을 선언합니다
후자를한다면 (그리고 일반적으로 원하는 것입니다) 해당 기능의 정의를 .cpp
파일 (또는 C ++ 소스 파일에 사용하는 모든 확장자). 그런 다음 해당 파일을 컴파일하고 결과 객체를 int128 유형을 사용하는 다른 코드와 연결합니다.
편집 : 여전히 비교 클리너를 만들 수 있습니다.
bool operator==(int128 const &o1, int128 const &o2)
{
return o1.storage[0] == o2.storage[0] && o1.storage[1] == o2.storage[1] &&
o1.storage[2] == o2.storage[2] && o1.storage[3] == o2.storage[3]);
}
다른 팁
링커는 여러 객체 파일에 여러 번 정의 된 기호가 있다고 주장합니다.
당신의 기능을 다음과 같이 선언하십시오 inline