为什么我们在这里需要typename?

template<class T> class Set { public: void insert(const T& item); void remove(const T& item); private: std::list<T> rep; } template<typename T> void Set<T>::remove(const T& item) { typename std::list<T>::iterator it = // question here std::find(rep.begin(),rep.end(),itme); if(it!=rep.end()) rep.erase(it); } 

为什么需要remove()中的typename?

一般来说,C ++需要typename因为它从Cinheritance的不幸的语法[*],这使得没有非本地信息就不可能说 – 例如 – 在A * B; A是否是一个types(在这种情况下,这是B一个指针),或者不是(在这种情况下,这是一个乘法expression式 – 很可能因为A ,所有你可以告诉没有非本地信息,可能是一个类的实例,重载operator*做一些奇怪的;-)。

在大多数情况下,编译器确实具有消除歧义所需的非本地信息(尽pipe不幸的语法仍然意味着低级parsing器需要来自保持符号表信息的较高层的反馈),但是使用模板,它不会(一般来说,虽然在这个特定情况下,从技术angular度来说,将std::list<T>进行专门化可能是非法的,所以它的::iterator不是types名称;-)。

不仅仅是我的意见,还有我的同事肯·汤普森(Ken Thompson)和罗伯·派克斯(Rob Pikes)的观点,他们正在忙于devise和实现一种新的内部使用的编程语言:新的编程语言,而其语法大部分是类C ,不重复C的语法devise错误 – 它是新的语言(就像例如在古老的Pascal中一样),语法足以区分必须命名types的标识符和不能; – )。

如果你正在谈论与std::list<T>::iterator一起使用的typename

typename用于说明iterator是在类std::list<T>定义的types。 没有typename, std::list<T>::iterator将被认为是一个静态成员。 只要依赖于模板参数的名称是types,就使用typename

在你的“it”声明中需要typename,否则编译器不知道它是一个types声明而不是expression式。

根据此页面 ,“如果具有引用types的限定名称并取决于模板参数,请使用关键字types名称”。

我认为一般来说,你需要在类声明中的typename / class T以及函数定义,因为你可以为函数定义定义全部/部分模板规范。 IE浏览器。 你可以专门化你的删除函数,整数,string,不pipe它发生什么。 所以在这种情况下,你告诉编译器“这是一般模板,对于任何types”,那么以后你可以定义只为整数指定的相同函数。