Как я могу использовать пользовательский тип для ключей в boost::unordered_map?
Я использую реализацию Boost хеш-карты в проекте прямо сейчас, и я пытаюсь реализовать пользовательский тип для ключей. У меня есть четыре целых числа без знака, которые я хотел бы объединить в один 128-битный тип данных для использования в качестве ключа.
Я создал структуру с 32-битным целочисленным массивом из четырех элементов, который служит моим хранилищем. Если честно, я не уверен, как работает хеш-карта Boost, поэтому я не уверен, что я здесь делаю, но я следовал документации Boost ( http://www.boost.org/doc/libs/1_37_0/doc/html/hash/custom.html) для расширения boost::hash, и я создал хеш-функцию, а также пользовательский оператор сравнения.
У меня есть этот пользовательский тип, определенный в заголовке. Это мой код:
#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-битный тип работал с этой картой. Любые советы о том, что я облажался, или лучший способ сделать это?
2 ответа
Участие неупорядоченной карты почти случайно связано с проблемой, с которой вы сталкиваетесь. Настоящая проблема в том, что вы определяете 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