一、与class的区别
template声明式中,class和typename这两个关键字意义完全相同
template<class T> class Widget;
template<typename T> class Widget;
二、什么时候要用typename?比如下面的代码
template <typename C>
void print2nd(const C& container)
{
if (container.size() >= 2)
{
C::const_iterator iter(container.begin());
++iter;
int value = *iter;
std::cout << value;
}
}
关键的地方在于C::const_iterator这个到底是什么?是类中的一个静态成员变量还是类中的嵌套从属名称?这取决于模板的参数C
这里的iterator就是嵌套从属名称
template <class T>
class test
{
vector <T> xx;
typename vector <T> ::iterator Iterator ; <=====这里必须加typename
};
在这里因为在编译期无法知道T是什么,也就无法确定iterator是否为某种类型,为了告诉编译器它是一种类型,必须在前面添加typename
三、嵌套从属名称可能导致解析的困难
template <typename C>
void print2nd(const C& container)
{
C::const_iterator* x;
}
这里有可能让编译误导是参数C中的某个静态成员变量与变量x作相乘,所以这里必须在前面添加typename
四、不该使用typename的地方
1、typename只用来验明嵌套从属类型名称;其他名称不该有它存在。
template <typename C>
void f(const C& container, //不允许使用typename
typename C::iterator iter);//一定要使用typename
2、“typename必须作为嵌套从属类型名称的前缀词”这一规则的例外是,typename不可以出现在base classes list内的嵌套从属类型名称之前,也不可在member initialization list(成员初始化列表)中作为base class修饰符。
template <typename T>
class Derived: public Base<T>::Nested{//base class list中不允许“typename”
public:
explicit Derived(int x)
:Base<T>::Nested(x)//mem.init.list中不允许“typename”
{
typename Base<T>::Nested temp;//嵌套从属类型既不在base class list中也不在mem.init.list中,
} //作为一个base class修饰符需加上typename
};
五、typename的使用例子
让我们看一个typename例子:一个function template,他接受一个迭代器,而我们打算为该迭代器指涉的对象做一份复件temp:
template <typename IterT>
void workWithIterator(IterT)
{
typename std::iterator_traits<IterT>::value_type temp(*iter);
}
也可以这么写,可以少打几个typedef typename std::iterator_traits<IterT>::value_type
template <typename IterT>
void workWithIterator(IterT)
{
typedef typename std::iterator_traits<IterT>::value_type value_type;
value_type temp(*iter);
来源:CSDN
作者:一缕阳光a
链接:https://blog.csdn.net/zgaoq/article/details/103462226