C++知識點59——類模板(4、類模板的模板引數是一個類模板)
阿新 • • 發佈:2020-12-28
接上一篇文章https://blog.csdn.net/Master_Cui/article/details/111824152
七、類模板的模板引數是一個模板類
類模板的模板引數本身可以是一個類模板,函式模板的模板引數不能是模板
依然用mystack作為示例,新的mystack的定義如下
template <typename T, int maxcount, template <typename ELE, typename alloc=allocator<ELE>> typename CONT = deque> class mystack { public: mystack(); mystack(const mystack<T, maxcount, CONT> &rval); mystack<T, maxcount, CONT> &operator=(const mystack<T, maxcount, CONT> &rval); template <typename T2, int maxcount2, template <typename ELE, typename alloc=allocator<ELE>> typename CONT2 = deque> mystack(const mystack<T2, maxcount2, CONT2> &rval); template <typename T2, int maxcount2, template <typename ELE, typename alloc=allocator<ELE>> typename CONT2 = deque> mystack<T, maxcount, CONT> &operator=(const mystack<T2, maxcount2, CONT2> &rval); ~mystack(); void push(const T &ele); void pop(); T top() const; bool empty() const { return elem.empty(); } private: CONT<T> elem; };
上述程式碼中,類模板的第二個模板引數也是個類模板,引數是ELE,預設實參是deque。因為第二個引數也是個類模板,所以不能寫成
template <typename T, int maxcount,
template <typename ELE, typename alloc=allocator<ELE>>
typename CONT = deque<T>>
否則,編譯器報錯
容器也從CONT elem;變成了CONT<T> elem;第二個引數類模板模板引數依賴第一個模板引數進行例項化
上述程式碼中,deque作為模板引數有兩個模板引數,當傳入一個deque或者其他容器時,自帶typename alloc,之後會對模板引數進行精確匹配,如果不寫,就會導致模板引數typename alloc匹配不正確。
所以,即使alloc是個預設模板引數,typename ELE和typename alloc=allocator<ELE>也缺一不可,否則,當建立一個模板類的例項時,就會提示引數不匹配
mystack的實現細節如下,和上一篇文章差別不大
template <typename T, int maxcount, template <typename ELE, typename alloc> typename CONT> mystack<T, maxcount, CONT>::mystack() { cout<<__func__<<endl; } template <typename T, int maxcount, template <typename ELE, typename alloc> typename CONT> mystack<T, maxcount, CONT>::mystack(const mystack<T, maxcount, CONT> &rval):elem(rval.elem) { cout<<__func__<<endl; } template <typename T, int maxcount, template <typename ELE, typename alloc> typename CONT> mystack<T, maxcount, CONT> & mystack<T, maxcount, CONT>::operator=(const mystack<T, maxcount, CONT> &rval) { cout<<__func__<<endl; if (this==&rval) { return *this; } this->elem=rval.elem; return *this; } template <class T, int maxcount, template <typename ELE, typename alloc> typename CONT> template <typename T2, int maxcount2, template <typename ELE2, typename alloc2> typename CONT2> mystack<T, maxcount, CONT>::mystack(const mystack<T2, maxcount2, CONT2> &rval) { cout<<__func__<<endl; mystack<T2, maxcount2, CONT2> tmp=rval; elem.clear(); while (!tmp.empty() && elem.size()<maxcount) { elem.push_front(tmp.top()); tmp.pop(); } } template <class T, int maxcount, template <typename ELE, typename alloc> typename CONT> template <typename T2, int maxcount2, template <typename ELE2, typename alloc> typename CONT2> mystack<T, maxcount, CONT> & mystack<T, maxcount, CONT>::operator=(const mystack<T2, maxcount2, CONT2> &rval) { cout<<__func__<<endl; if ((void*)(this)==(void*)(&rval)) { return *this; } mystack<T2, maxcount2, CONT2> tmp=rval; elem.clear(); while (!tmp.empty() && elem.size()<maxcount) { elem.push_front(tmp.top()); tmp.pop(); } return *this; } template <typename T, int maxcount, template <typename ELE, typename alloc> typename CONT> mystack<T, maxcount, CONT>::~mystack() { cout<<__func__<<endl; } template <typename T, int maxcount, template <typename ELE, typename alloc> typename CONT> void mystack<T, maxcount, CONT>::push(const T &ele) { if (elem.size()>=maxcount) { return; } //cout<<__func__<<endl; elem.push_back(ele); } template <typename T, int maxcount, template <typename ELE, typename alloc> typename CONT> void mystack<T, maxcount, CONT>::pop() { //cout<<__func__<<endl; try { elem.pop_back(); } catch (out_of_range &e){ cout<<"out_of_range"<<endl; } } template <typename T, int maxcount, template <typename ELE, typename alloc> typename CONT> T mystack<T, maxcount, CONT>::top() const { //cout<<__func__<<endl; try { return elem.back(); } catch (out_of_range &e){ cout<<"out_of_range"<<endl; } }
int main(int argc, char const *argv[])
{
mystack<int, 10, list> si10;
for (int i=0;i<10;++i) {
si10.push(i);
}
mystack<double, 20> sd20;
for (int i=0;i<20;++i) {
sd20.push(i);
}
si10=sd20;
while(!si10.empty()) {
cout<<si10.top()<<endl;
si10.pop();
}
mystack<double, 10> sd10=si10;
mystack<int, 10> si101=si10;
return 0;
}
測試結果和前一篇文章相同
參考
《C++ Template》
《C++ Primer》
歡迎大家評論交流,作者水平有限,如有錯誤,歡迎指出