template<typename T> classStack{ private: std::vector<T> elems; // elements public: voidpush(T const &elem); // push elem voidpop(); // pop element T const &top()const; // return top element boolempty()const{ // return whether the stack is empty return elems.empty(); } };
template<typename T> T Stack<T>::pop() { assert(!elems.empty()); T elem = elems.back(); // save copy of last element elems.pop_back(); // remove last element return elem; // return copy of saved element }
template<typename T> T const &Stack<T>::top() const { assert(!elems.empty()); return elems.back(); // return copy of last element }
template<typename T> classStack{ ... voidprintOn(std::ostream& strm)const{ for(T const & elem : elems){ strm << elem << ' '; // call << for each element } } };
尽管如此,不支持<<操作符的T也是可以使用的。
1 2 3 4 5
Stack<std::pair<int, int>> ps; // note: std::pair<> has no operator<< defined ps.push({4, 5}); // OK ps.push({6, 7}); // OK std::cout << ps.top().first << '\n'; // OK std::cout << ps.top().second << '\n'; // OK
然而一旦使用了:
1
ps.printOn(std::cout); // ERROR: operator<< not supported for element type
template<> classStack<std::string>{ private: std::deque<std::string> elems; // elements public: voidpush(std::stringconst&); // push elements voidpop(); // pop element std::stringconst &top()const; //return top element boolempty()const{ // return whether the stack is empty return elems.empty(); } };
// partial specialization of class Stack<> for pointers: template<typename T> classStack<T*>{ private: std::vector<T*> elems; // elements public: voidpush(T*); // push elements T* pop(); // pop element T* top()const; // return top element boolempty()const{ // return whether the stack is empty return elems.empty(); } }; template<typename T> T* Stack<T*>::pop() { assert(!elems.empty()); T* p = elems.back(); elems.pop_back(); // remove last element return p; // and return it (unlike in the general case) } template<typename T> T* Stack<T*>::top() const { assert(!elems.empty()); return elems.back(); // return copy of last element }
// the following partial specializations are possible: // partial specialization: both template parameters have same type template<typename T> classMyClass<T, T>{ ... };
// partial specialization: second type is int template<typename T> classMyClass<T, int>{ ... };
// partial specialization: both template parameters are pointer types template<typename T1, typename T2> classMyClass<T1*, T2*>{ ... };
#include<vector> #include<cassert> template<typename T, typename Cont = std::vector<T>> class Stack{ private: Cont elems; // elements public: voidpush(T const& elem); // push element voidpop(); // pop element T const &top()const; // return top element boolempty()const{ // return whether the stack is empty return elems.empty(); } }
template<typename T, typename Cont> void Stack<T, Cont>::push(T const& elem) { elems.push_back(elem); // append copy of passed elem } template<typename T, typename Cont> void Stack<T, Cont>::pop() { assert(!elems.empty()); elems.pop_back(); // remove last element } template<typename T, typename Cont> T const& Stack<T,Cont>::top() const { assert(!elems.empty()); return elems.back(); // return copy of last element }
intmain() { // stack of ints Stack<int> intStack; // stack of doubles using a std::deque<> to manage the elements Stack<double,std::deque<double>> dblStack; // manipulate int stack intStack.push(7); std::cout << intStack.top() << '\n'; intStack.pop(); // manipulate double stack dblStack.push(42.42); std::cout << dblStack.top() << '\n'; dblStack.pop(); }
类型别名
C++的语法过于啰嗦,所以通过alias定义可以简化语法。
使用typedef。
1 2 3 4
typedef Stack tpedef Stack<int> IntStack; // typedef voidfoo(IntStack const& s); // s is stack ofints IntStack istack[10]; // istack is array of 10 stacks of ints
俗称的typedef-name。
使用C++11引入的using关键字。
1 2 3
using IntStack = Stack<int>; // alias declaration voidfoo(IntStack const& s); // s is stack of ints IntStack istack[10]; // istack is array of 10 stacks of ints