看一下自定义类型如何在函数头返回类定义的类型:
一个vec初略模板:
template <class T> class Vec { public: typedef T* iterator; typedef const T* const_iterator; typedef size_t size_type; typedef T value_type; typedef T& reference; typedef const T& const_reference; iterator erase(iterator it); ....... ... private: .... };
要实现erase函数,返回值为iterator,下面的函数定义可以吗?
template<class T> Vec<T>::iterator Vec<T>::erase(iterator it) { ......... }
上面的是错误的,应该在
Vec<T>::iterator
前加typename关键字。如下:
template<class T> typename Vec<T>::iterator Vec<T>::erase(iterator it) { ......... }
为什么要加typename,因为iterator这个类型是在Vec<T>类定义的。C++规定:无论何时,如果使用了一个依赖与模板参数的类型时(如vector<T>),而且你想要使用这个类型的成员函数(如size_type)本身就是一个类型,就必须在整个名字前加上typename。
现在要你写一个求vector中值的模板函数,想想怎么写。
template<class T>
T median(vector<T> v) { typedef typename vector<T>::size_type vec_sz; vec_sz size=v.size(); if(size==0) throw.domain_error("median of an empty vector"); sort(v.begin(),v.end()); vec_sz mid=size/2; return size%2==0?(v[mid]+v[mid-1]):v[mid]); }
上面的typename告诉系统:vector<T>::size_type 是一个类型的名字,虽然系统并不知道类型T是什么,无论什么时候,如何你使用一个依赖于模板参数的类型时,比如vector<T>,而且 你想要使用这个类型的成员时,比如size_type,它本身也是一个类型时,你必须在整个名字之前加上typename,以便让系统知道要把这个名字当成类型来对待。
msdn解释:
The typename keyword tells the compiler that an unknown identifier is a type.
typename identifier;
Use this keyword only in template definitions. For example:
// typename.cpp
template<class T> class X
{
typename T::Y m_y; // treat Y as a type
};
int main()
{
}
This keyword can also be used in place of class in template parameter lists. For example, the following statements are identical:
template<class T1, class T2>... template<typename T1, typename T2>...
深入:
http://pages.cs.wisc.edu/~driscoll/typename.html