C++ 非类型模板参数(3)---《C++ Templates》

摘要:
1)template parameters不限只能是类型,也可以是数值;
2)不能将浮点数(历史原因)、class-type对象、内部链接对象当做nontype template parameters的自变量。

非类型模板参数

本篇博文中以创建一个固定大小的Stack为例,来加以理解非类型模板参数:

#include <stdexcept>
template <typename T,int MAXSIZE>
class Stack{
private:
    T elems[MAXSIE];
    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 std::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 std::out_of_range("Stack<>::pop(): empty stack.");
    }
    --numElems;
}
template <typename T,int MAXSIZE>
T Stack<T,MAXSIZE>::top() const{
    if(numElems<=0){
        throw std::out_of_range("Stack<>::top(): empty stack.");
    }
    return elems[numElems-1];
}

#include <iostream>
#include <string>
#include <cstdlib>
#include "stack.hpp"

int main(){
    try{
        Stack<int,20> int20Stack;
        Stack<int,40> int40Stack;
        Stack<std::string,40> stringStack;
        int20Stack.push(7);
        std::cout<<int20Stack.top<<std::endl;
        int20Stack.pop();
        stringStack.push("hello");
        std::cout<<stringStack.top()<<std::endl;
        stringStack.pop();
        stringStack.pop();
    }catch(std::exception const&ex){
        std::cerr<"Exception:"<<ex.what()<<std::endl;
        return EXIT_FAILURE;
    }
}       

需要注意的是,每一个被实例化的class template都有各自的类型,因此int20Stack和int40Stack是两个不同的乐行,不能互相进行隐式类型转换,更不能互相赋值。
我们也可以给non-type template parameters设定默认值:

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

Nontype Function Template Parameter

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

当我们需要将函数或者某种通用操作作为参数传递时,这一类型就非常有用,如我们可以运用上述的function template的实例,将某值加到元素集内的每一个元素升上:

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

但上述的代码中存在问题,addValue

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

Nontype Template Parameter的局限性

Nontype Template Parameters可以使用整型类型、enum、指向外部链接的指针或者引用,同时不能把普通局部对象或者动态对象绑定到指针或者引用的非类型模板参数上面,以及全局指针也不可以,可以使用全局类型绑定,因为绑定非类型模板参数的形参必须是常量表达式。
以浮点数或者class-type objects作为nontype template parameters是不可以的。

template <char const* name>
class MyClass{
    ...
};
MyClass<"hello"> x;//错误,不能使用字符串变量“hello”
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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值