在函数模板中创建一个containor迭代器
creating a containor iterator inside a function template
代码是使用GCC编译的。这项工作在VC++中没有任何错误
template <typename T>
void Function(T& A){
T::iterator it; //Error : dependent-name 'T::iterator' is parsed as a non-type,
//but instatiation yields a type.
}
本文指出编译器无法判断T
类型中的迭代器是类还是静态成员。因此,我们必须使用typename
关键字来将符号分类为一种类型。
我的问题是,由于T
在编译时是已知的,那么编译器已经知道T中的iterator
是一个类(在我的情况下,T是vector<int>
)。那么,为什么会出现错误呢?
除了将typename
关键字用作定义模板参数T
之外,这也是对它的另一种使用。
更新:
我从这里读到了所有的答案和其他答案,它们真的回答了我所有的想法。我可以总结为:
处理此权限的正确编译器是Gcc。VC++将允许您编译格式错误的代码。使用Gcc编译时发生的错误是由于语法分析,因为Gcc会尝试解析函数模板的代码,但它会发现一个语法错误T::iterator it;
,因为Deafault的Gcc将T::iterator
视为变量(T::iterator
被解析为非类型)而不是类型,要解决这个问题,必须明确地告诉Gcc,将T::iterator
视为类型,这是通过添加关键字CCD_ 12来完成的
现在回到VC++。之所以能做到这一点,是因为VC++中存在错误,这是因为VCC++是否延迟了T::iterator
是变量还是类型的决定。或者VC++在其认为需要的任何地方提供关键字CCD_ 14
有用的文章
注意:如果您发现不正确的地方,请随时编辑UPDATE。
您参考的文章提供了解释:
编译器必须被告知指定的符号实际上是一种类型,而不是给定类的静态符号。
考虑本文中的一个例子:
class ContainsAType {
class iterator { ... }:
...
};
class ContainsAValue {
static int iterator;
};
因此,在上面的Function()
中,编译器必须知道T::iterator
是类型还是静态变量。typename
关键字消除了C++中的歧义。
此线程包含一些关于在类似情况下使用typename的良好讨论。
我的问题是,由于T在编译时是已知的,那么编译器已经知道T中的迭代器是一个类(在我的情况下,T是向量)。
是的,这就是为什么VC++可以不使用typename关键字。
那么,为什么会出现错误呢?
因为标准规定模板名称查找应该分两个阶段进行。在某些情况下,这需要消除歧义(见此)。因此,GCC中会出现错误,因为它符合repsect中的两阶段名称查找标准。另一方面,VC++使用了一种后期解析方案。
正如DeadMG所指出的,当编译器无法诊断缺失的类型名时,VC++的方法可能会失败,并产生更复杂的代码。
看看这个线程。
当编译器看到T::iterator it;
时,它还不知道T
是什么。只有当您调用函数(实例化时间)时,它才会知道T
是什么。这是两阶段名称查找的一部分,在第一阶段,编译器检查Function
的声明是否存在语法错误,并查找所有非依赖名称。这有助于在定义点检测错误,而不是等到实例化点。
例如:
template <typename T>
struct A
{
X x;
};
struct X{};
int main()
{
A<int> a;
}
一个好的编译器会查找X
并告诉你它不知道它是什么。然而,MSVC编译器会接受这个格式错误的代码。
这里是另一个例子:
template <typename T>
class A : public I_do_not_exist
{
};
一个好的编译器会告诉你I_do_not_exist
不存在(MSVC编译这个代码)。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 从链接列表c++中删除一个项目
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '