1、例子
#include "iostream"
using namespace std;
template<class K>
class HashTableIterator {
};
template<class K>
class HashTable {
public:
typedef HashTableIterator<K> iterator;
typedef int it;
static const int b = 10;
int a;
};
template<class K>
class myUnorderSet {
public:
typename HashTable<K>::it i = 1;
HashTable<K>::iterator a
typedef HashTable<K>::iterator b;
};
int main(){
HashTable<int>::it a = 10;
cout << a << endl;
typedef HashTable<int>::it i;
return 0;
}
Missing ‘typename’ prior to dependent type name ‘HashTable::iterator’
2、解释
对于用于模板定义的依赖于模板参数的名称,只有在实例化的参数中存在这个类型名,或者这个名称前使用了 typename 关键字来修饰,编译器才会将该名称当成是类型。除了以上这两种情况,绝不会被当成是类型。
也就是说HashTable<K>::iterator a
编译器根本不知道iterator
是个啥,是变量还是类型?默认编译器是识别为变量的,因此clion检测到了错误,vs中就不会有红色波浪形提示。
因此,如果你想直接告诉编译器 HashTable<K>::iterator
是类型而不是变量,只需用 typename修饰:typename HashTable<K>::it
,这样编译器就可以确定 HashTable<K>::iterator
是一个类型,而不再需要等到实例化时期才能确定,因此消除了前面提到的歧义。
而自己写迭代器时,还用了typedef,变成typedef typename HashTable<K>::iterator b;
将b声明为iterator类型的别名。
3、综上
要用到一个类模版里面定义的类型时,要么在用这个类模版里面定义的类型时前面加上typename,要么将这个类模版实例化