gpt4 book ai didi

C++:将自定义哈希键值从 unordered_map 输出到 std::cout 时出错

转载 作者:行者123 更新时间:2023-11-28 06:23:43 24 4
gpt4 key购买 nike

我正在尝试构建一个 std::unordered_map以自定义类型作为键。自定义类型是一个简单的 std::vector<double> .这个想法是它将作为网格上 2D 点的方便容器。除了输出散列 key 外,一切正常。这是我放在一起来说明这个想法的示例:

#include <iostream>
#include <vector>
#include <unordered_map>
#include <boost/functional/hash.hpp>
#include <chrono>

namespace std
{
template<typename Container>
struct hash {
std::size_t operator()(Container const& v) const
{
return boost::hash_range(v.begin(), v.end());
}
};
}

int main()
{

std::unordered_map<std::vector<double>, double> test;

unsigned long t = (unsigned long) std::chrono::system_clock::now().time_since_epoch().count();
std::srand(t);
for (uint i = 0; i < 100 ; ++i)
{
double d1 = i/200.0;
double d2 = i/200.0;
std::vector<double> v({d1, d2});
test[v] = d1;
}

std::cout << "Size:" << test.size() << std::endl;
for (const auto& it : test )
{
std::cout << it.first << ":" << it.second << std::endl;
}

return 0;
}

散列特化模板由另一个 SO 线程提供。问题是当我尝试编译上面的代码时 g++ 吐出以下错误:

cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
std::cout << it.first << ":" << it.second << std::endl;
^

很明显它偶然发现了it.first .如果我删除 it.first,代码将正确编译和运行.我知道输出将不是是 double vector 。我确实环顾四周了很长一段时间,但我找不到关于如何 std::cout 的明确答案。来自具有自定义键类型的无序映射的哈希值。任何反馈将不胜感激。

提前致谢!

编辑:

谢谢大家的意见。这是我第一次遇到非原始类型作为散列键,所以我对键/值对的存储方式有错误的想法(我假设散列值是键,而实际上它是实际的自定义类型) .

最佳答案

value_typeunordered_map<K,V>pair<const K, V> .这就是您使用范围遍历它时得到的结果。没有 operator<< vector 过载s,导致您看到的错误。


namespace std
{
template<typename Container>
struct hash {
std::size_t operator()(Container const& v) const
{
return boost::hash_range(v.begin(), v.end());
}
};
}

这不是 std::hash 的特化.这是对主模板的重新定义,在您的情况下,主模板仅由纯偶然事件编译。 (实现必须保留主 std::hash 模板未定义,并且必须在 hash 命名空间而不是内联命名空间中实际声明 std。例如,您的代码 breaks up completely on libc++。)

特化看起来像

namespace std
{
// full specialization
template<>
struct hash<Foo> {
// ^^^^^
std::size_t operator()(Foo const& v) const
{
// ...
}
};

// partial specialization
template<typename T>
struct hash<Bar<T>>{
// ^^^^^^^^
std::size_t operator()(Bar<T> const& v) const
{
// ...
}
};
}

注意 hash 之后的显式模板参数列表.这表明这是一个特化。

特化是非法的std::hash对于 std::vector<double>无论如何,因为它不依赖于用户定义的类型。编写自己的哈希器很容易:

struct container_hasher {
template<typename Container>
std::size_t operator()(Container const& v) const
{
using std::begin;
using std::end;
return boost::hash_range(begin(v), end(v));
}
};

请注意,我模板化了 operator()而不是类型本身——这使得编写哈希类型更容易。 using随后是一个不合格的调用,为 begin 启用 ADL和 end .

然后是test的定义成为

std::unordered_map<std::vector<double>, double, container_hasher> test;

关于C++:将自定义哈希键值从 unordered_map 输出到 std::cout 时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28891143/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com