1. 程式人生 > 其它 >C++知識點59——類模板(4、類模板的模板引數是一個類模板)

C++知識點59——類模板(4、類模板的模板引數是一個類模板)

技術標籤:C++基礎c++泛型

接上一篇文章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》

歡迎大家評論交流,作者水平有限,如有錯誤,歡迎指出