概念一个模板的参数是模板类型。 举例在c++11-17 模板核心知识(二)—— 类模板 中,如果我们想要允许指定存储Stack元素的容器,是这么做的: template <typename T, typename Cont = std::vector<T>> class Stack { private: Cont elems; // elements ...... }; 使用: Stack<double,std::deque<double>> dblStack; 但是这样的缺点是需要指定元素类型两次,然而这两个类型是一样的。 使用模板的模板参数(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(); } ... }; 使用: Stack<int, std::vector> vStack; // integer stack that uses a vector 与第一种方式的区别是:第二个模板参数是一个类模板: template<typename Elem> class Cont 默认值从 在C++17之后,模板的模板参数中的class也可以使用typename,但是不可以使用struct和union: 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 ... }; 模板的模板参数的参数匹配 Template Template Argument Matching大家可以尝试自己编译一下上面的代码,可能会出现下列问题: 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>*/> 意思是 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 { ...... }; 但是,这点对于 // template<typename T, size_t N> // class array; 假如使用 /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> ^ (完) |
|