C++模板类型名迭代器
C++ template typename iterator
请考虑以下头文件:
template <typename T> struct tNode
{
T Data; //the data contained within this node
list<tNode<T>*> SubNodes; //a list of tNodes pointers under this tNode
tNode(const T& theData)
//PRE: theData is initialized
//POST: this->data == theData and this->SubNodes have an initial capacity
// equal to INIT_CAPACITY, it is set to the head of SubNodes
{
this->Data = theData;
SubNodes(INIT_CAPACITY); //INIT_CAPACITY is 10
}
};
现在考虑另一个文件中的一行代码:
list<tNode<T>*>::iterator it(); //iterate through the SubNodes
编译器给我这个错误消息:Tree.h:38:17: error: need ‘typename’ before ‘std::list<tNode<T>*>::iterator’ because ‘std::list<tNode<T>*>’ is a dependent scope
我不知道为什么编译器为此对我大喊大叫。
在 list<tNode<T>*>::iterator
中,您有一个依赖名称,即依赖于模板参数的名称。
因此,编译器无法检查list<tNode<T>*>
(此时它没有定义),因此它不知道list<tNode<T>*>::iterator
是静态字段还是类型。
在这种情况下,编译器假定它是一个字段,因此在您的情况下,它会产生语法错误。要解决此问题,只需通过在声明之前放置一个typename
来告诉编译器它是一个类型:
typename list<tNode<T>*>::iterator it
首先,正如其他答案已经指出的那样,嵌套到依赖类型的类型名称需要加上 typename
关键字。
当模板完全专用时不需要该关键字,这意味着list<tnode<int>*>::iterator
不需要typename
,但是当外部类仍然依赖于模板参数T
时,必须存在typename
。
template <typename T> void foo() {
list<tnode<int>*>::iterator it1; // OK without typename
typename list<tnode<T>*>::iterator it2; // typename necessary
}
其次,即使typename
typename list<tNode<T>*>::iterator it();
声明将声明一个函数,而不是一个迭代器。删除()
。
list<tNode<T>*>::iterator
是一个依赖名称,一种依赖于模板参数的类型。为了声明该变量,您需要使用 typename
关键字:
typename list<tNode<T>*>::iterator it = ...;
有关上述答案的更多背景资料,请点击此处
C++类型名称关键字的说明
我有一个不同但类似的问题,因为我想用 :
typedef std::vector<NodeType*>::iterator ChildIterator;
这给了我相同的编译器错误。有了这里的建议和上述链接的帮助,我的问题的解决方案是使用
typedef typename std::vector<NodeType*>::iterator ChildIterator;
相反。
迭代器可以是嵌套类和类属性
typename
关键字解决的歧义是,T::iterator
(或在您的案例中list<tNode<T>*>::iterator
)可以指nested type
(案例 1)或static class attribute
(案例 2)。默认情况下,编译器将这样的构造解释为大小写 2。typename
关键字强制执行大小写 1。
下面的示例演示了案例 1 和案例 2 的实现。在这两种情况下,都会显示行T::iterator * iter;
。在情况 1 中,它仅在前面附加 typename
参数时才有效。在情况 2 中,它只表示一个双精度(没有任何操作)。星号 * 只是添加的,因为它在情况 1 中是指针的指示符,在情况 2 中是乘法运算符。
最小可重现示例
#include <iostream>
template <class T>
void foo1() {
typename T::iterator * iter;
std::cout << "foo1: iter points to: " << iter << std::endl;
}
class class1 {
public:
class iterator // subclass
{
};
};
template <class T>
void foo2() {
double iter = 2.;
T::iterator * iter;
std::cout << "foo2: "T::iterator * iter" is a simple double: " << T::iterator * iter << std::endl;
}
class class2 {
public:
constexpr static double iterator = 11.;
};
int main()
{
foo1<class1>();
foo2<class2>();
// foo1<class2>(); // does not compile
// foo2<class1>(); // does not compile
return 0;
}
输出
foo1: iter points to: 0x4010b0
foo2: "T::iterator * iter" is a simple double: 22
感谢 trueter 指出文章 C++ typename 关键字的描述。这个答案基本上是一个简短的总结。
- 如何在c++迭代器类型中包装std::chrono
- 定义模板参数的迭代器类型
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- C++不兼容的迭代器类型
- 如何推导 std::高级迭代器类型?
- 在 stl 容器包装器中定义迭代器类型
- 矢量迭代器类型未知
- STD ::向量迭代器类型和允许的操作
- 检查容器模板类中的迭代器类型
- 如何断言模板参数的类型 STL 迭代器类型
- 检测容器是否具有迭代器类型
- 由set2.begin()返回的迭代器类型
- 序列容器的迭代器类型是什么?
- 如何推断嵌套最多的迭代器类型
- 为什么迭代器类型与矢量容器中的 value_type * 不匹配
- ISO C++禁止声明没有自动迭代器类型的“it”
- 使用的迭代器类型错误
- 列表的迭代器类型
- 如何打印迭代器类型列表<pair<int,int>>::iterator itrator it指向的元素
- 为什么 void* 不是迭代器类型?