接上一篇文章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》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出