1. 从属名称与非从属名称
- 如果tempalte内某个名称依赖于某个template参数,我们称这个参数为从属名称(dependent names)
比如C::const_iterator这个参数类型就是从属名称,依赖于C的类型。
- 如果不依赖任何其他参数,称为非从属名称(non dependent names)
这就是具体的,不依赖其他类型的参数类型:比如int ,float 这种具体的。
2. 传递模板类型的从属名称参数需要在参数前加上typename
- 传递带typename的参数:如print2nd()函数
#include <iostream> #include <vector> using namespace std; template <typename C> // 参数必须加typename, 不能这么写void print2nd(const C &container, C::const_iterator iter) void print2nd(const C &container, typename C::const_iterator iter) { //... // 错误写法:C::const_iterator* iter1; cout << "test " << *(++iter) << endl; // 20 } int main() { vector<int> aa; aa.push_back(10); aa.push_back(20); aa.push_back(21); print2nd(aa, vector<int>::const_iterator(aa.begin())); }
- 为什么需要在C::const_iterator前面加上typename呢?因为其实编译器在编译的时候,如果不加typename,也就没办法去保证C::const_iterator是一个数据类型
比如const_iterator是class C的一个static成员变量,那么C::const_iterator* iter1;就会变成两个数(C::const_iterator和iterator1)相乘。但如果加上typename,那么我就能知道C::const_iterator是一种数据类型。传入C能够知道是某个类型的具体数据。
3. 传入一个template参数,并且为之复制一个局部变量
#include <iostream> #include <vector> using namespace std; template <typename Iter> void print2nd(Iter iter) { // Iter就是一种参数类型 Iter local_tmp = iter; std::cout << *local_tmp << endl; // 10 // 从属名称 typename vector<int>::iterator::value_type local_tmp2 = *iter; std::cout << local_tmp2 << endl; // 10 // vector<int>::iterator可等价为传入的Iter typename Iter::value_type local_tmp3 = *iter; std::cout << local_tmp3 << endl; // 10 } int main() { vector<int> aa; aa.push_back(10); aa.push_back(20); aa.push_back(21); vector<int>::iterator tmp(aa.begin()); print2nd(tmp); }