【发布时间】:2016-08-31 17:26:52
【问题描述】:
以下代码实现了 std::tuple 的哈希函数,然后在 std::unordered_map 的 std::tuples 的 std::unordered_map 中用于我的代码库的不同段。
// compute hash function recursively through each std::tuple element
template<class Tuple, std::size_t N>
struct tuple_hash_compute {
static std::size_t hash_compute(const Tuple& t) {
using type = typename std::tuple_element<N-1, decltype(t)>::type; // OFFENDING LINE
return tuple_hash_compute<Tuple, N-1>::hash_compute(t)
+ std::hash<type>()(std::get<N-1>(t));
}
};
// base helper
template<class Tuple>
struct tuple_hash_compute<Tuple, 1> {
static std::size_t hash_compute(const Tuple& t) {
using type = typename std::tuple_element<0, decltype(t)>::type; // OFFENDING LINE
return 51U + std::hash<type>()(std::get<0>(t))*51U;
}
};
// tuple_hash function object
struct tuple_hash {
template<class... Args>
std::size_t operator()(const std::tuple<Args...>& t) const {
return tuple_hash_compute<decltype(t), sizeof...(Args)>::hash_compute(t);
}
// will use std::unordered_map of std::pair too, so overload reqd
template<class Ty1, class Ty2>
std::size_t operator()(const std::pair<Ty1, Ty2>& p) const {
return tuple_hash_compute<decltype(t), 2>::hash_compute(p);
}
};
然后,作为一个例子,我会像这样使用这个散列函数对象,
std::unordered_map<std::tuple<int,int,int>, std::size_t, tuple_hash> agg_map;
agg_map.insert(std::make_pair(std::make_tuple(1,2,3), 0U));
agg_map.insert(std::make_pair(std::make_tuple(4,5,6), 1U));
但是,在GCC 6.1.0 和MSVC2015 中,我都收到以下错误(以上每个违规行都相同):
错误:不完整类型'
class std::tuple_element<2ul, const std::tuple<int,int,int>&>'的使用无效
我不完全确定是什么导致了这个错误(尽管它可能是由于通过模板参数std::tuple 传递std::tuple 的“抽象”)或如何解决它,因此感谢您的帮助。
【问题讨论】:
-
也许使用
Tuple而不是decltype(t)? -
@PiotrSkotnicki 恐怕我已经尝试过了并且收到了同样的错误。
-
@PiotrSkotnicki 嗯,有趣,好的,我现在可以在
GCC中使用它(也许我以某种方式错过了相关的#include)但它仍然不喜欢MSVC2015- 我在这种情况下得到use of undefined type std::tuple_element<2, Tuple>作为错误。 -
@PiotrSkotnicki 啊,没关系,我没有意识到你也替换了那行 - 它现在在 GCC 和 MSVC 中都可以使用,谢谢 :) 把它写成答案,我会接受它(一旦我吃完饭回来),虽然我很好奇为什么这种改变会起作用。
标签: c++ c++14 stdtuple stdhash