当前位置:嗨网首页>书籍在线阅读

23-将模板用作参数

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

14.4.8 将模板用作参数

您知道,模板可以包含类型参数(如typename T)和非类型参数(如int 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> s1;
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()的模板类。本章恰巧有一个这样的类——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表示非模板类型。