如何在 boost::unordered_map 中使用自定义类型的键?

发布于 2024-08-12 15:38:04 字数 1681 浏览 7 评论 0原文

我现在正在项目中使用 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 位类型与这张地图一起工作。关于我搞砸的事情有什么建议,或者更好的方法吗?

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_37_0/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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

朱染 2024-08-19 15:38:04

无序映射的参与几乎是您遇到的问题的偶然。真正的问题是您在包含上述标头的每个文件中定义 hash_valueoperator==

您可以通过以下任一方法解决此问题:

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

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]);
}
苹果你个爱泡泡 2024-08-19 15:38:04

链接器声称我有一个符号
多次定义
目标文件。

将您的函数声明为内联

The linker claims that I have a symbol
defined multiple times in several
object files.

declare your functions as inline

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文