一、typename 的用法
1、typename 和 class 在模板定义中,声明模板参数为类型参数时,可以互换。
template<typename T>
T Add(T val1, T val2)
template<class T>
T Add(T val1, T val2)
2、使用类的类型成员时,用 typename 标识其后跟的是个类型。
例一
template<typename T>
class myvector
{
public:
typedef T* myiterator; // 用 typedef 定义的为类型成员
public:
myiterator mybegin(); // 返回容器中的第一个元素
};
template<typename T>
// 1. 需要用 myvector<T>:: 访问类型成员 myiterator
// 2. 编译器只有在实例化时才能确定 myvector<T>:: 后面跟着的是类型还是静态成员变量,所以需要用 typename标识其后跟着的是类型。
typename myvector<T>::myiterator myvector<T>::mybegin()
{
//todo
}
例二
size_type 为 string / STL 的类型成员, typedef usigned int size_type
typename 表示 T::size_type 返回的也是一个类型
template<typename T>
typename T::size_type getlength(const T& c)
{
return c.size();
}
string str = "hello world";
cout << getlength(str) << endl;
二、函数指针作其他函数的参数
// 定义函数指针类型
typedef int (*FunType)(int, int);
int myfunc(int val1, int val2)
{
return val1 + val2;
}
void recvfunc(int i, int j, FunType pf)
{
cout << pf(i, j) << endl;
}
int main()
{
recvfunc(1, 2, myfunc);
return 0;
}
三、函数指针作为函数模板参数
下面的例子中,编译器将模板参数 F 解释成函数指针类型 FunType
typedef int (*FunType)(int, int);
int myfunc(int val1, int val2)
{
return val1 + val2;
}
template<typename T, typename F>
void tfunc(const T &i, const T &j, F pf)
{
cout << pf(i, j) << endl;
}
int main()
{
tfunc(1, 2, myfunc);
return 0;
}
四、对象作为函数模板参数
template<typename T, typename F>
void tfunc(const T &i, const T &j, F pf)
{
cout << pf(i, j) << endl;
}
class Test
{
public:
Test() { cout << "construct" << endl; }
Test(const Test& t) { cout << "copy construct" << endl; }
int operator()(int v1, int v2) const
{
return v1 + v2;
}
};
int main()
{
Test t; // 调用构造函数
tfunc(1, 2, t); // 调用拷贝构造函数
}
执行结果:
image.png
上面的程序中,编译器将模板参数 F 解释为 Test 类型对象(因为在 Test 类中重载了括号Test(int, int),所以Test类对象可以当作函数调用的格式使用),并将 t 传递给了 pf (pf相当于临时对象),调用了拷贝构造函数。
使用临时对象:
int main()
{
tfunc(2, 3, Test());
}
执行结果:
image.png
使用临时对象,则模板函数直接承接此临时对象,省去了拷贝构造过程(也省去一次析构过程),更加节省时空。
五、默认模板参数
类模板
类模板的实例化必须显示声明模板参数(<>不可省略)
类模板的缺省参数
template<typename T=string, int size=10>
class myarray
{
private:
T arr[size];
};
int main()
{
// 完全使用模板参数缺省值
myarray<> arr1;
// 使用部分模板参数缺省值
myarray<int> arr2;
return 0;
}
函数模板
C++11 开始,支持函数模板默认参数
例一: 对象作为函数模板默认参数
class Test
{
public:
Test() { cout << "construct" << endl; }
Test(const Test& t) { cout << "copy construct" << endl; }
int operator()(int v1, int v2) const
{
return v1 + v2;
}
};
// 为 F 提供默认参数 Test 类
template<typename T, typename F=Test>
// 为 pf 提供临时对象 F(),即为Test()
void tfunc(const T &i, const T &j, F pf=F())
{
cout << pf(i, j) << endl;
}
int main()
{
tfunc(2, 5);
return 0;
}
例二:函数指针作为函数模板默认参数
typedef int (*FunType)(int, int);
int myfunc(int val1, int val2)
{
return val1 + val2;
}
// 为 F 提供默认参数 FunType 类型
template<typename T, typename F=FunType>
// pf 默认为 myfunc
void tfunc(const T &i, const T &j, F pf=myfunc)
{
cout << pf(i, j) << endl;
}
int main()
{
tfunc(2, 5);
return 0;
}
例三:函数模板的默认非类型参数
template<int T=10>
void tfunc()
{
cout << T << endl;
}
int main()
{
tfunc(); // 输出10
tfunc<>(); // 输出 10
tfunc<12>(); // 输出12
return 0;
}
网友评论