一、模板模板参数的使用
模板模板参数的英文为
T
e
m
p
l
a
t
e
T
e
m
p
l
a
t
e
P
a
r
a
m
e
t
e
r
s
Template \ Template \ Parameters
Template Template Parameters,实际上就是使用模板参数本身成为模板。
我们看下面的例子:
如果我们要实现一个自定义容器,以
s
t
d
:
:
v
e
t
c
o
r
std::vetcor
std::vetcor作为默认容器类型,那么我们可能会写出以下代码:
template<typename T,typename Container = std::vector>
class mylist {
private:
Container<T>myli;
};
但是这样的代码不能通过编译,因为我们传入的 C o n t a i n e r Container Container是一个类模板容器,编译器不能识别出来,因此我们需要使用到模板模板参数,如下所示:
//template<typename T,template<typename > typename Container = std::vector>
//使用class也可以
template<typename T, template<class> class Container = std::vector>
class myvector {
private:
Container<T> myvec;
public:
myvector() {
std::cout << "调用了myvector的构造函数\n";
};
//....//
};
随着
C
+
+
C++
C++新标准的不断引入,可以使用
t
y
p
e
n
a
m
e
typename
typename逐渐替代
c
l
a
s
s
class
class了。
因此下面两种形式都是可以的:
t
e
m
p
l
a
t
e
<
t
y
p
e
n
a
m
e
T
,
t
e
m
p
l
a
t
e
<
t
y
p
e
n
a
m
e
>
t
y
p
e
n
a
m
e
C
o
n
t
a
i
n
e
r
template<typename \ T,template<typename > typename \ Container
template<typename T,template<typename>typename Container
t
e
m
p
l
a
t
e
<
t
y
p
e
n
a
m
e
T
,
t
e
m
p
l
a
t
e
<
c
l
a
s
s
>
c
l
a
s
s
C
o
n
t
a
i
n
e
r
=
s
t
d
:
:
v
e
c
t
o
r
>
template<typename \ T, template<class> class \ Container = std::vector>
template<typename T,template<class>class Container=std::vector>
对于不使用的模板参数名称,也可以省略。通常,嵌套内层的参数是用不到的,可以省略名称:
//省略名称
//如果有的名称没有被使用,则可以不需要写出来。
template<typename, template<typename>typename = std::vector>
class myvector3 {
//不使用名称
//...//
};
注意的是,内层嵌套的模板参数名称,不能被外层的类模板所使用,如:
//嵌套的模板定义的参数不能被外层使用
template<typename T,template<typename U>typename Container = std::vector>
class myvector2 {
private:
Container<T>myvec;
public:
//U my_vari; //无法使用U类型,因为在嵌套内的参数列表
};
因为 U U U类型实在嵌套模板内的,所以这里类内无法使用 U U U类型。
二、成员函数的实现
对于成员函数,在类内实现很简单,直接实现即可:
emplate<typename T, template<typename>typename Container= std::vector >
class myvector4{
private:
Container<T> myvec;
public:
myvector4() {};
myvector4(size_t n, T val = {}) {
myvec.resize(n, val);
}
//类内实现成员函数
void push_back(T const& val) {
myvec.push_back(std::move(val));
}
void print();
};
我们尝试在类外实现一下 p r i n t print print函数,如下:
//类外实现成员函数
//类外不能指定参数,因为一开始实例化的时候已经指定过了
template<typename T, template<typename>typename Container /* = std::vector*/ >
void myvector4<T, Container>::print() {
for (auto const& val : myvec) {
std::cout << val << " ";
}
std::cout << std::endl;
}
注意在类外声明参数的时候不要使用默认参数,因为成员函数只有在调用时才会实例化,而参数类型在创建类的时候就被实例化了,所以不能指定。
运行一下:
void Test2() {
myvector4<std::string>myvec;
myvec.push_back("hello");
myvec.push_back("world");
myvec.push_back("!");
myvec.print();
}
成功调用了了成员函数: