c++11-17模板核心知识(十二)——模板的模板参数TemplateTemplatePa。。。

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

c++11-17模板核⼼知识(⼗⼆)——模板的模板参数
TemplateTemplatePa。

朋友们可以关注下我的公众号,获得最及时的更新:
概念
⼀个模板的参数是模板类型。

举例
在中,如果我们想要允许指定存储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
默认值从std::deque<T>改为了std::deque.
在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>*/>
意思是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
}
解决办法⼆
利⽤
template <typename T,
template <typename......>
class Cont = std::deque>
class Stack {
......
};
但是,这点对于std::array⽆效,因为std::array的第⼆个参数是:
// 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>
^
:22:33: note: previous template template parameter is here
template <typename... Elem>
^
(完)
朋友们可以关注下我的公众号,获得最及时的更新:。

相关文档
最新文档