c++ template学习总结【转】

 
  1. #include <stdexcept>    
  2.   
  3. template <typename T, int MAXSIZE>    
  4. class Stack {    
  5.   private:    
  6.     T elems[MAXSIZE];        // elements    
  7.     int numElems;            // current number of elements    
  8.   public:    
  9.     Stack();                 // constructor    
  10.     void push(T const&);     // push element    
  11.     void pop();              // pop element    
  12.     T top() const;           // return top element    
  13.     bool empty() const {     // return whether the stack is empty    
  14.         return numElems == 0;    
  15.     }    
  16.     bool full() const {      // return whether the stack is full    
  17.         return numElems == MAXSIZE;    
  18.     }    
  19. };    
  20.   
  21. // constructor    
  22. template <typename T, int MAXSIZE>    
  23. Stack<T,MAXSIZE>::Stack ()    
  24.   : numElems(0)              // start with no elements    
  25. {    
  26.     // nothing else to do    
  27. }    
  28.   
  29. template <typename T, int MAXSIZE>    
  30. void Stack<T,MAXSIZE>::push (T const& elem)    
  31. {    
  32.     if (numElems == MAXSIZE) {    
  33.         throw std::out_of_range("Stack<>::push(): stack is full");    
  34.     }    
  35.     elems[numElems] = elem;  // append element    
  36.     ++numElems;              // increment number of elements    
  37. }    
  38.   
  39. template<typename T, int MAXSIZE>    
  40. void Stack<T,MAXSIZE>::pop ()    
  41. {    
  42.     if (numElems <= 0) {    
  43.         throw std::out_of_range("Stack<>::pop(): empty stack");    
  44.     }    
  45.     --numElems;              // decrement number of elements    
  46. }    
  47.   
  48. template <typename T, int MAXSIZE>    
  49. T Stack<T,MAXSIZE>::top () const    
  50. {    
  51.     if (numElems <= 0) {    
  52.         throw std::out_of_range("Stack<>::top(): empty stack");    
  53.     }    
  54.     return elems[numElems-1];  // return last element    
  55. }   
#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 
} 

 

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

  1. #include <iostream>    
  2. #include <string>    
  3. #include <cstdlib>    
  4. #include "stack4.hpp"    
  5.   
  6. int main()    
  7. {    
  8.     try {    
  9.         Stack<int,20>         int20Stack;    // stack of up to 20 ints    
  10.         Stack<int,40>         int40Stack;    // stack of up to 40 ints    
  11.         Stack<std::string,40> stringStack;   // stack of up to 40 strings    
  12.   
  13.         // manipulate stack of up to 20 ints    
  14.         int20Stack.push(7);    
  15.         std::cout << int20Stack.top() << std::endl;    
  16.         int20Stack.pop();    
  17.   
  18.         // manipulate stack of up to 40 strings    
  19.         stringStack.push("hello");    
  20.         std::cout << stringStack.top() << std::endl;    
  21.         stringStack.pop();    
  22.         stringStack.pop();    
  23.     }    
  24.     catch (std::exception const& ex) {    
  25.         std::cerr << "Exception: " << ex.what() << std::endl;    
  26.         return EXIT_FAILURE;  // exit program with ERROR status    
  27.     }    
  28. }   
#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是两个不同的类型,他们是不能进行硬是或者显示的转换的。也不能够相互赋值。

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

  1. template <typename T, int VAL>    
  2. T addValue (T const& x)    
  3. {    
  4.     return x + VAL;    
  5. }   
template <typename T, int VAL> 
T addValue (T const& x) 
{ 
    return x + VAL; 
} 

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

  1. std::transform (source.begin(), source.end(),  // start and end of source    
  2.                 dest.begin(),                  // start of destination    
  3.                 addValue<int,5>);              // operation   
std::transform (source.begin(), source.end(),  // start and end of source 
                dest.begin(),                  // start of destination 
                addValue<int,5>);              // operation 

有时候我们为了使得编译器推导的时候简单一些,可以使用:

  1. std::transform (source.begin(), source.end(),  // start and end of source    
  2.                 dest.begin(),                  // start of destination    
  3.                 (int(*)(int const&)) 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作为非类型模板参数是错误的:

  1. template <double VAT>        // ERROR: floating-point values are not    
  2. double process (double v)    //        allowed as template parameters    
  3. {    
  4.     return v * VAT;    
  5. }    
  6.   
  7. template <std::string name>  // ERROR: class-type objects are not    
  8. class MyClass {              //        allowed as template parameters    
  9.   …    
  10. };   
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 
  … 
}; 

 

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

  1. template <char const* name>    
  2. class MyClass {    
  3.   …    
  4. };    
  5.   
  6. MyClass<"hello"> x;   // ERROR: string literal "hello" not allowed   
template <char const* name> 
class MyClass { 
  … 
}; 

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

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

  1. template <char const* name>    
  2. class MyClass {    
  3.   …    
  4. };    
  5.   
  6. char const* s = "hello";    
  7.   
  8. MyClass<s> x;         // ERROR: s is pointer to object with internal linkage   
template <char const* name> 
class MyClass { 
  … 
}; 

char const* s = "hello"; 

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

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

  1. template <char const* name>    
  2. class MyClass {    
  3.   …    
  4. };    
  5.   
  6. extern char const s[] = "hello";    
  7.   
  8. MyClass<s> x;        // OK   
template <char const* name> 
class MyClass { 
  … 
}; 

extern char const s[] = "hello"; 

MyClass<s> x;        // OK 

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


============================================================================== 我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其实我是一个程序员。
posted @ 2012-03-08 18:51  simple99  阅读(108)  评论(0编辑  收藏  举报