为什么编译器对此模板存在作用域问题
Why does the compiler have scoping issues with this template?
我发现自己经常从vector
中删除元素,而不关心顺序的维护,这意味着使用擦除删除将是浪费。最好将要移除的元素与最后一个元素和pop_back()
交换。在标准库中似乎没有任何东西可以做到这一点,所以我试图编写自己的模板,但我真的没有牢牢掌握模板语法。
我写了这个:
template<typename T>
void unordered_erase(std::vector<T>& vec, const std::vector<T>::iterator& it)
{
if (it != vec.end())
{
std::swap(vec.back(), *it);
vec.pop_back();
}
}
然而编译器抱怨道。
error: need ‘typename’ before ‘std::vector<_RealType>::iterator’ because ‘std::vector<_RealType>’ is a dependent scope
所以我修改了它,它编译了。
template<typename T>
void unordered_erase(std::vector<T>& vec, const typename std::vector<T>::iterator& it)
{
if (it != vec.end())
{
std::swap(vec.back(), *it);
vec.pop_back();
}
}
我真正不明白的是,编译器怎么能推导出std::vector<T>
而不能推导出std::vector<T>::iterator
?
编译器能够推导出类型T
。std::vector<_RealType>::iterator
没有被推导出来,它是std::vector
的一种嵌入类型。
需要typename
,以便编译器能够从成员变量名称中消除嵌入类型名称的歧义。
来自cppreference;
在模板(包括别名模板)的声明或定义中,不属于当前实例化的成员并且依赖于模板参数的名称不被视为类型,除非使用关键字
typename
,或者除非它已经被建立为类型名称,例如使用typedef
声明或用于命名基类。
当可能存在歧义时,名称依赖于模板参数,编译器需要假设名称是成员变量的名称,而不是类型的名称。
相关文章:
- 未在作用域中声明unordered_map
- 有没有一种方法可以在编译时获得作用域类名
- C++quit()函数中可能存在作用域问题
- 未在此作用域OpenCV3.4中声明cvSaveImage
- 全局作用域中函数指针的赋值
- 在类函数中初始化外部作用域变量
- 不同作用域中的静态变量和全局变量
- 是同一作用域的函数部分中的函数调用
- 未在此作用域中声明的函数和变量 (C++)
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 将作用域枚举转换为基础类型
- 表达式必须具有完整或无作用域的枚举图
- 在构造函数中输入对象时C++类成员作用域
- 无法让"std::enable_if"适用于无作用域枚举
- C2386:"void_t":当前作用域中已存在具有此名称的符号
- 未在此作用域中声明函数,即使存在头文件也是如此
- 为什么编译器对此模板存在作用域问题
- 如果在同一作用域中存在同名的类和变量,如何指定该类
- 如果存在,则使用它/检测C++中当前作用域的调用约定(thiscall vs cdecl)
- 模板类的实例之间是否存在共享的作用域