23-将模板用作参数
14.4.8 将模板用作参数
您知道,模板可以包含类型参数(如typename T)和非类型参数(如int n)。模板还可以包含本身就是模板的参数,这种参数是模板新增的特性,用于实现STL。
在程序清单14.21所示的示例中,开头的代码如下:
template <template <typename T> class Thing>
class Crab
模板参数是template
Crab<King> legs;
为使上述声明被接受,模板参数King必须是一个模板类,其声明与模板参数Thing的声明匹配:
template <typename T>
class King {...};
在程序清单14.21中,Crab的声明声明了两个对象:
Thing<int> s1;
Thing<double> s2;
前面的legs声明将用King
Crab<Stack> nebula;
因此,Thing
Crab类的声明对Thing代表的模板类做了另外3个假设,即这个类包含一个push()方法,包含一个pop()方法,且这些方法有特定的接口。Crab类可以使用任何与Thing类型声明匹配,并包含方法push()和pop()的模板类。本章恰巧有一个这样的类——stacktp.h中定义的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";
return 0;
}
下面是程序清单14.21所示程序的运行情况:
Enter int double pairs, such as 4 3.5 (0 0 to end):
50 22.48
25 33.87
60 19.12
0 0
60, 19.12
25, 33.87
50, 22.48
Done.
可以混合使用模板参数和常规参数,例如,Crab类的声明可以像下面这样打头:
template <template <typename T> class Thing, typename U, typename V>
class Crab
{
private:
Thing<U> s1;
Thing<V> s2;
...
现在,成员s1和s2可存储的数据类型为泛型,而不是用硬编码指定的类型。这要求将程序中nebula的声明修改成下面这样:
Crab<Stack, int, double> nebula; // T=Stack, U=int, V=double
模板参数T表示一种模板类型,而类型参数U和V表示非模板类型。