首页 > 代码库 > 非类型模板参数

非类型模板参数

对于函数模板与类模板,模板参数并不局限于类型,普通值也可以作为模板参数。在基于类型参数的模板中,你定义了一些具体的细节来加以确定代码,直到代码被调用时这些细节才被真正的确定。但是在这里,我们面对的是这些细节是值,而不是类型,当要使用基于值的模板时,必须显式地指定这些值,才能够对模板进行实例化。

非类型的类模板参数

 

创建类的头文件

#include<stdexcept>#include<iostream>using namespace std;template<typename T, int MAXSIZE>class Stack{private:    T elems[MAXSIZE];    int numElems;public:    Stack();    void push(T const&);    void pop();    T top() const;    bool empty() const {        return numElems == 0;    }    bool full() const {        return numElems == MAXSIZE;    }};template<typename T, int MAXSIZE>Stack<T, MAXSIZE>::Stack():numElems(0) {}template<typename T, int MAXSIZE>void Stack<T, MAXSIZE>::push(T const& elem){    if(numElems == MAXSIZE) {        throw out_of_range("Stack<>::push(): stack is full");    }    elems[numElems] = elem;    ++numElems;}template<typename T, int MAXSIZE>void Stack<T, MAXSIZE>::pop(){    if(numElems <= 0) {        throw out_of_range("Stack<>::pop(): stack is full");    }    --numElems;}template<typename T, int MAXSIZE>T Stack<T, MAXSIZE>::top() const{    if(numElems <= 0) {        throw out_of_range("Stack<>::top(): stack is full");    }    return elems[numElems - 1];}

#include<stdexcept>#include<iostream>using namespace std;template<typename T, int MAXSIZE>class Stack{private:    T elems[MAXSIZE];    int numElems;public:    Stack();    void push(T const&);    void pop();    T top() const;    bool empty() const {        return numElems == 0;    }    bool full() const {        return numElems == MAXSIZE;    }};template<typename T, int MAXSIZE>Stack<T, MAXSIZE>::Stack():numElems(0) {}template<typename T, int MAXSIZE>void Stack<T, MAXSIZE>::push(T const& elem){    if(numElems == MAXSIZE) {        throw out_of_range("Stack<>::push(): stack is full");    }    elems[numElems] = elem;    ++numElems;}template<typename T, int MAXSIZE>void Stack<T, MAXSIZE>::pop(){    if(numElems <= 0) {        throw out_of_range("Stack<>::pop(): stack is full");    }    --numElems;}template<typename T, int MAXSIZE>T Stack<T, MAXSIZE>::top() const{    if(numElems <= 0) {        throw out_of_range("Stack<>::top(): stack is full");    }    return elems[numElems - 1];}

实现代码:

#include<iostream>#include<vector>#include<deque>#include<stdexcept>#include<string>#include<cstdlib>#include "stack4.h"using namespace std;int main(){    try {        Stack<int, 20> int20Stack;        Stack<int, 40> int40Stack;        Stack<string, 40> stringStack;                int20Stack.push(7);        cout<<int20Stack.top()<<endl;        int20Stack.pop();        stringStack.push("hello");        cout<<stringStack.top()<<endl;        stringStack.pop();        stringStack.pop();    }    catch(exception const& ex) {        cerr<<"Exception: "<<ex.what()<<endl;        //return EXIT_FAILURE;    }        cin.get();      return 0;}

#include<iostream>#include<vector>#include<deque>#include<stdexcept>#include<string>#include<cstdlib>#include "stack4.h"using namespace std;int main(){    try {        Stack<int, 20> int20Stack;        Stack<int, 40> int40Stack;        Stack<string, 40> stringStack;                int20Stack.push(7);        cout<<int20Stack.top()<<endl;        int20Stack.pop();        stringStack.push("hello");        cout<<stringStack.top()<<endl;        stringStack.pop();        stringStack.pop();    }    catch(exception const& ex) {        cerr<<"Exception: "<<ex.what()<<endl;        //return EXIT_FAILURE;    }        cin.get();      return 0;}

MAXSIZE是新加入的第二个模板参数,类型为int,它指定了数组最多可包含的栈元素的个数
同样,我们可以为模板参数指定缺省值:

template<typename T = int, int MAXSIZE = 100>class Stack {    ...};

  非类型的函数模板参数

你也可以为函数模板定义非类型参数。例如:

template<typename T, int VAL>T addValue(T const& x){    return x + VAL:}

借助于STL,可以传递这个函数模板的实例化给集中的每一个元素,让他们都增加一个整数值:

std::transform(source.begin(), source.end(), dest.begin(), (int(*)(int const&))addValue<int, 5>);

  非类型模板参数的限制

非类型模板参数是有限制的,通常而言,它们可以是常整数(包括枚举值)或者指向外部链接对象的指针。

浮点数和类对象是不允许作为非类型模板参数的:

template<double VAT>double process(double v) //error{    return V * VAT;}template<string name>  //errorclass MyClass {    ...};

  另外,你也不能使用全局指针作为模板参数

template<char const* name>class MyClass{    ...};char const* s = "hello";MyClass<s> x;   //s是一个指向内部连接对象的指针

但是你可以这样使用:

template<char const* name>class MyClass {    ...};extern char const s[] = "hello";MyClass<s> x;  //OK

全局字符数组s由"hello"初始化,是一个外部链接对象

非类型模板参数