条款typename的双重定义
声明关键字class和typename可互换
假设你这样声明一个迭代器 C::const_iterator iter(container.begin());
这将不是一个有效的c++代码。
因为 C::const_iterator如果不是一个类型呢?如果C 有个成员变量恰好命名为const_iterator。如果他碰巧是个全局变量呢?
当然这听上去有点疯狂,但确实是有可能的,而撰写c++解析器的人必须操心所有可能的输入,包括这么疯狂的输入
如果你想在template中指涉一个嵌套从属类型名称,就必须在紧邻它的前一个位置放上关键字typename
下面是代码环节:
#include <iostream>
#include<vector>
using namespace std;
/*
template<typename C>
void print2nd(const C& container)
{
if (container.size() >= 2)
{
typename C::const_iterator iter(container.begin());
++iter;
int value = *iter;
cout << value;
}
}
*/
template<class C>
void print2nd(const C& container)
{
if (container.size() >= 2)
{
class C::const_iterator iter(container.begin());
++iter;
int value = *iter;
cout << value;
}
}
int main()
{
vector<int> res;
res.push_back(1);
res.push_back(2);
print2nd(res);
return 0;
}
运行结果:
但有一例外,typename不可以出现在base classes list内的嵌套从属类型名称之前。
也不能在成员初值列中
其他都可以
#include <iostream>
#include<vector>
using namespace std;
template<typename T>
class MyNested
{
public:
MyNested(T x) :value(x) { cout << value << endl; }
T value;
};
template<typename T>
class Base
{
public:
typedef MyNested<T> Nested;
};
template<typename T>
class Dervied:public Base<typename T>::Nested
{
public:
explicit Dervied(int x) : Base<T>::Nested(x)
{
typename Base<T>::Nested temp(5);
}
private:
};
int main()
{
Dervied<int> d(7);
return 0;
}
运行结果:
最后
当使用特性类(traits class)时, 必须使用typename, 如
#include <vector>
#include <iostream>
using namespace std;
template<typename T>
void workWithIter(T iter) {
typedef typename std::iterator_traits<T>::value_type value_type; //使用typename
value_type temp(*iter);
std::cout << "temp = " << temp << std::endl;
}
int main() {
vector<int> ai = { 1,2,3,4,5 };
vector<int>::iterator aiIter = ai.begin();
workWithIter(aiIter);
return 0;
}
运行结果: