一個模板的參數是模板類型。c++
在c++11-17 模板核心知識(二)—— 類模板 中,若是咱們想要容許指定存儲Stack元素的容器,是這麼作的:git
template <typename T, typename Cont = std::vector<T>> class Stack { private: Cont elems; // elements ...... };
使用:github
Stack<double,std::deque<double>> dblStack;
可是這樣的缺點是須要指定元素類型兩次,然而這兩個類型是同樣的。app
使用模板的模板參數(Template Template Parameters),容許咱們在聲明Stack類模板的時候只指定容器的類型而不去指定容器中
元素的類型。例如:函數
template <typename T, template <typename Elem> class Cont = std::deque> class Stack { private: Cont<T> elems; // elements public: void push(T const &); // push element void pop(); // pop element T const &top() const; // return top element bool empty() const { // return whether the stack is empty return elems.empty(); } ... };
使用:c++11
Stack<int, std::vector> vStack; // integer stack that uses a vector
與第一種方式的區別是:第二個模板參數是一個類模板:code
template<typename Elem> class Cont
默認值從std::deque<T>
改成了std::deque
.element
在C++17以後,模板的模板參數中的class也可使用typename,可是不可使用struct和union:get
template <typename T, template <typename Elem> typename Cont = std::deque> class Stack { // ERROR before C++17 ... }; ...... template<template<typename X> class C> // OK void f(C<int>* p); template<template<typename X> struct C> // ERROR: struct not valid here void f(C<int>* p); template<template<typename X> union C> // ERROR: union not valid here void f(C<int>* p);
固然,因爲模板的模板參數中的Elem沒有用到,能夠省略:編譯器
template <typename T, template <typename> class Cont = std::deque> class Stack { ... };
另外注意一點,模板的模板參數中的模板參數,只能和模板的模板參數配合用。有點饒,舉個例子:
template<template<typename T, T*> class Buf> // OK class Lexer { static T* storage; // ERROR: a template template parameter cannot be used here ... };
你們能夠嘗試本身編譯一下上面的代碼,可能會出現下列問題:
error: template template argument has different template parameters than its corresponding template template parameter template <typename T, template <typename Elem> class Cont = std::deque> ... /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/deque:1197:1: note: too many template parameters in template template argument template <class _Tp, class _Allocator /*= allocator<_Tp>*/>
意思是std::deque
和Cont
不匹配。標準庫的std::deque
有兩個參數,還有一個默認參數Allocator :
template <class _Tp, class _Allocator = allocator<_Tp> > class _LIBCPP_TEMPLATE_VIS deque;
將Cont和std::deque的參數匹配便可:
template <typename T, template <typename Elem, typename Alloc = std::allocator<Elem>> class Cont = std::deque> class Stack { ...... };
這裏的Alloc沒有用到,一樣能夠省略。
成員函數定義舉例:
template<typename T, template<typename,typename> class Cont> void Stack<T,Cont>::push (T const& elem) { elems.push_back(elem); // append copy of passed elem }
利用c++11-17 模板核心知識(四)—— 可變參數模板 Variadic Template
template <typename T, template <typename......> class Cont = std::deque> class Stack { ...... };
可是,這點對於std::array
無效,由於std::array的第二個參數是非類型模板參數 Nontype Template Parameters:
// template<typename T, size_t N> // class array;
假如使用 Stack<int,std::array> s;
,那麼編譯器會報錯:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/array:126:29: note: template parameter has a different kind in template argument template <class _Tp, size_t _Size> ^ main.cc:22:33: note: previous template template parameter is here template <typename... Elem> ^
(完)
朋友們能夠關注下個人公衆號,得到最及時的更新: