c++ template学习总结3


和往常一样,先来看一段代码:

#include <stdexcept> 

template <typename T, int MAXSIZE> 
class Stack { 
  private: 
    T elems[MAXSIZE];        // elements 
    int numElems;            // current number of elements 
  public: 
    Stack();                 // constructor 
    void push(T const&);     // push element 
    void pop();              // pop element 
    T top() const;           // return top element 
    bool empty() const {     // return whether the stack is empty 
        return numElems == 0; 
    } 
    bool full() const {      // return whether the stack is full 
        return numElems == MAXSIZE; 
    } 
}; 

// constructor 
template <typename T, int MAXSIZE> 
Stack<T,MAXSIZE>::Stack () 
  : numElems(0)              // start with no elements 
{ 
    // nothing else to do 
} 

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;  // append element 
    ++numElems;              // increment number of elements 
} 

template<typename T, int MAXSIZE> 
void Stack<T,MAXSIZE>::pop () 
{ 
    if (numElems <= 0) { 
        throw std::out_of_range("Stack<>::pop(): empty stack"); 
    } 
    --numElems;              // decrement number of elements 
} 

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];  // return last element 
} 

接下来编写我们的测试函数:

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

int main() 
{ 
    try { 
        Stack<int,20>         int20Stack;    // stack of up to 20 ints 
        Stack<int,40>         int40Stack;    // stack of up to 40 ints 
        Stack<std::string,40> stringStack;   // stack of up to 40 strings 

        // manipulate stack of up to 20 ints 
        int20Stack.push(7); 
        std::cout << int20Stack.top() << std::endl; 
        int20Stack.pop(); 

        // manipulate stack of up to 40 strings 
        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;  // exit program with ERROR status 
    } 
} 

大家要注意int20Stack和int40Stack是两个不同的类型,他们是不能进行硬是或者显示的转换的。也不能够相互赋值。

你还可以为函数模板定义非型别参数:

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

当我们想把【函数】和某种操作作为参数传递的时候,就非常有用,比如在使用STL时,你可能有下面的代码:

std::transform (source.begin(), source.end(),  // start and end of source 
                dest.begin(),                  // start of destination 
                addValue<int,5>);              // operation 
有时候我们为了使得编译器推导的时候简单一些,可以使用:
std::transform (source.begin(), source.end(),  // start and end of source 
                dest.begin(),                  // start of destination 
                (int(*)(int const&)) addValue<int,5>);  // operation 

但是我们要注意,非类型模板参数也有自己的局限,通常来说他们只能是常整数,包括枚举,或者指向外部链接的指针。如果我们用浮点数或者class-type objects作为非类型模板参数是错误的:

template <double VAT>        // ERROR: floating-point values are not 
double process (double v)    //        allowed as template parameters 
{ 
    return v * VAT; 
} 

template <std::string name>  // ERROR: class-type objects are not 
class MyClass {              //        allowed as template parameters 
  … 
}; 

由于字串字面常熟是一种采用内部链接的物件,也就是说不通模组中的两个同值的字串字面常数其实是两个不同的东西,所以他们也不能用来作为模板参数:

template <char const* name> 
class MyClass { 
  … 
}; 

MyClass<"hello"> x;   // ERROR: string literal "hello" not allowed 

此外全局指针也是不行的:

template <char const* name> 
class MyClass { 
  … 
}; 

char const* s = "hello"; 

MyClass<s> x;         // ERROR: s is pointer to object with internal linkage 

但是下面的例子是可以的:

template <char const* name> 
class MyClass { 
  … 
}; 

extern char const s[] = "hello"; 

MyClass<s> x;        // OK 

在这个例子中,s是一个外部连接的部件。

优质内容筛选与推荐>>
1、Beta冲刺NO.7
2、mysql索引的注意事项
3、用GDB调试程序(五)
4、centos6 安装xhprof扩展
5、将日期转为中文字符的类


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn