使用std::tuple_element时无效使用不完整类型的问题
Issue with invalid use of incomplete type when using std::tuple_element
下面的代码实现了std::tuple
的哈希函数,然后在std::tuple
s的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>&>
'
我不完全确定是什么原因导致这个错误(虽然它可能是由于通过模板参数Tuple
传递std::tuple
的"抽象")或如何解决它,所以任何帮助是感激的。
对于如下声明的参数:
const Tuple& t
decltype(t)
产量:
const Tuple&
类似地,对于声明为:
的形参:const std::pair<Ty1, Ty2>& t
decltype(t)
产率:
const std::pair<Ty1, Ty2>&
在这两种情况下,生成的类型都是对类元组类型的引用。然而,std::tuple_element
不是专门用于引用的,这意味着编译器会退回到主的、未定义的类模板:
template <size_t I, typename T> class tuple_element;
您想要的是,在前一种情况下是普通的Tuple
,在后一种情况下是std::pair<Ty1, Ty2>
。
如果类型Tuple
可能是引用也可能不是引用,则可以像这样使用std::remove_reference
:
typename std::tuple_element<num, typename std::remove_reference<Tuple>::type>::type
,对于c++ 17,
std::tuple_element_t<num, std::remove_reference_t<Tuple>>
PS:我不认为它适用于std::reference_wrapper
虽然…
相关文章:
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 类中的字符串不命名类型
- 不完整类型错误(E0409、E0070、E0515)
- CRTP 单一实例不完整类型或非文本类型
- 使用具有结构不完整类型错误的模板
- 哪些存储了不完整类型的 STL 数据结构可以用作类成员?
- Xalloc 不命名类型
- (结构名/类名)不命名类型C++
- 是否允许类类型的 std::function 成员变量(不完整类型)?
- MSVC 在不知道类型的情况下评估上下文(和错误)
- 为什么我得到变量"Node"不是类型名称错误
- Visual Studio Code "variable " u8 的 C/C++ 扩展名 " " 不是类型名称"
- 将"std::string {aka std::basic_string}"赋值中的不兼容类型<char>
- 实例化具有不完整类型的类模板格式不正确(如果该类型是在之后定义的)
- C++ 外部类不命名类型
- 有没有办法用不变语法获得当前的类类型?
- 标准容器模板可以用不完整类型实例化吗?
- 什么时候不能用“类”代替“类型名”
- 用Clang编译c++11代码的不完整类型
- 为什么C++不能用 "super class" 类型的右值初始化 "derived class" 类型的变量?