如何在boost :: unordered_map中为键使用自定义类型? [英] How can I use a custom type for keys in a boost::unordered_map?

查看:1338
本文介绍了如何在boost :: unordered_map中为键使用自定义类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在使用Boost的哈希映射在项目中的实现,我试图实现一个自定义类型的键。我有四个无符号整数,我想把它们组合成一个128位的数据类型作为键。



我创建了一个32位的结构, 4位元整数数组,作为我的存储。说实话,我不知道Boost的哈希映射如何工作,所以我不知道我在这里做什么,但我按照Boost文档( http://www.boost.org/doc/libs/1%5F37%5F0/doc/html/ hash / custom.html )用于扩展boost :: hash,我创建了一个哈希函数,以及一个自定义比较运算符。



我有这个在标题中定义的自定义类型。这是我的代码:

  #ifndef INT128_H_ 
#define INT128_H_

//自定义128位数据类型,用于存储和比较弱化的散列运算的结果。
struct int128
{
unsigned int storage [4];

/ *分配操作,需要一个包含四个元素的32位整数数组。
这使得值的赋值更短,更少痛苦的操作。 * /
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;
}

//散列函数使int128使用boost :: hash。
std :: size_t hash_value(int128 const& input)
{
boost :: hash< unsigned long long>哈希尔
unsigned long length 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 == 。 / p>

您可以通过以下方式解决此问题:

  1. 定义这两个作为内联函数

  2. 只要在标题中声明它们

如果你做后者(这是你通常想要的)你将这些函数的定义移动到 .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]);
}


I'm using Boost's implementation of a hash map in a project right now, and I'm trying to implement a custom type for keys. I have four unsigned integers which I'd like to combine into a single 128-bit datatype to use as a key.

I've created a struct with a 32-bit integer array of four elements, which serves as my storage. To be honest, I'm not sure how Boost's hash map works, so I'm not sure what I'm doing here, but I followed the Boost documentation (http://www.boost.org/doc/libs/1%5F37%5F0/doc/html/hash/custom.html) for extending boost::hash, and I created a hash function, as well as a custom comparison operator.

I have this custom type defined in a header. This is my code:

#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

Now when I actually use this type in Boost's unordered map, my code compiles, but fails to link. The linker claims that I have a symbol defined multiple times in several object files. I'd really like to get my 128-bit type working with this map. Any tips on what I'm screwing up, or a better way to do this?

解决方案

The involvement of unordered-map is almost incidental to the problem you're encountering. The real problem is that you're defining hash_value and operator== in every file that includes the header above.

You can cure this by either:

  1. Defining both those as inline functions
  2. Just declaring them in the header

If you do the latter (and it's what you'll usually want) you'll move the definitions of those functions into a .cpp file (or whatever extension you use for C++ source files). You'll then compile that file, and link the resulting object with your other code that uses the int128 type.

Edit: You can still make your comparison cleaner, something like:

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]);
}

这篇关于如何在boost :: unordered_map中为键使用自定义类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆