C++Primer Plus 第十四章代码重用:14.4.8 将模板用作参数
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
14.4.8 将模板用作参数
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
#14.4.8 将模板用作参数
您知道,模板可以包含类型参数(如typename T)和非类型参数(如imnt n)。模板还可以包含本身就是模板的参数,这种参数是模板新增的特性,用于实现 STL。
在程序清单14.21所示的示例中,开头的代码如下:
template <template <typename T>class Thing>
class Crab
模板参数是 template class Thing,其中 template class 是类型,Thing 是参数。这意味着什么呢?假设有下面的声明:
crab<King> legs;
为使上述声明被接受,模板参数 King 必须是一个模板类,其声明与模板参数Thing 的声明匹配:
template <typename T>
class King...);
在程序清单14.21中,Crab的声明声明了两个对象:
Thing<int> sl;
Thing<double>s2;
前面的 legs 声明将用 King替换 Thing,用 King替换 Thing。然而,程序清单14.21包含下面的声明:
Crab<Stack> nebula;
因此,Thing将被实例化为 Stack,而 Thing将被实例化为 Stack。总之,模板参数 Thing 将被替换为声明 Crab 对象时被用作模板参数的模板类型。
Crab 类的声明对 Thing 代表的模板类做了另外3个假设,即这个类包含一个 push()方法,包含一个 pop()方法,且这些方法有特定的接口。Crab类可以使用任何与Thing类型声明匹配,并包含方法 push()和 pop()的模板类。本章恰巧有一个这样的类–stacktph中定义的 Stack 模板,因此这个例子将使用它。
程序清单14.21 tempparm.cpp
// tempparm.cpp ?templates as parameters
#include <iostream>
#include "stacktp.h"
template <template <typename T> class Thing>
class Crab
{
private:
Thing<int> s1;
Thing<double> s2;
public:
Crab() {};
// assumes the thing class has push() and pop() members
bool push(int a, double x) { return s1.push(a) && s2.push(x); }
bool pop(int & a, double & x){ return s1.pop(a) && s2.pop(x); }
};
int main()
{
using std::cout;
using std::cin;
using std::endl;
Crab<Stack> nebula;
// Stack must match template <typename T> class thing
int ni;
double nb;
cout << "Enter int double pairs, such as 4 3.5 (0 0 to end):\n";
while (cin>> ni >> nb && ni > 0 && nb > 0)
{
if (!nebula.push(ni, nb))
break;
}
while (nebula.pop(ni, nb))
cout << ni << ", " << nb << endl;
cout << "Done.\n";
// cin.get();
// cin.get();
return 0;
}
下面是程序清单 14.21所示程序的运行情况:
可以混合使用模板参数和常规参数,例如,Crab类的声明可以像下面这样打头:
template <template <typename T> class Thing,
typename U, typename V>class Crab
{
private:
Thing<U> sl;
Thing<V> s2;
}
现在,成员s1和s2可存储的数据类型为泛型,而不是用硬编码指定的类型。这要求将程序中nebula的声明修改成下面这样:
Crab<Stack,int,double>nebula;//T=Stack,U=int,V=double模板参数T表示一种模板类型,而类型参数U和V表示非模板类型。