C++11 模板学习

基本概念

模板是一种支持参数化多态的工具,使得程序员能够编写与类型无关的代码

模板又分为两种:函数模板和类模板

模板特化

模板特化的提出是根据C++的设计,对于特定的类型,如果你能对某个功能有更好的实现,那么应该听你的。特化必须要在同一个命名空间下进行,函数模板只可以全特化(因为偏特化可以通过函数重载实现),而类模板则可以偏特化或者是全特化。

因此在模板实例化时,会优先匹配参数类型最匹配的那个特化版本。

  • 全特化

通过全特化模板,可以对某些特定参数集合自定义功能。此时模板参数为空。如:

1
2
3
4
5
6
7
8
9
10
11
12
//类模板
template <>
class A<int, double>{
int data1;
double data2;
};

//函数模板
template <>
int max(const int lhs, const int rhs) {
return lhs > rhs ? lhs : rhs;
}

注意:类模板需要在类名后面给出模板参数,而函数则不需要,它可以自动推导。

  • 偏特化

例如,针对vector进行偏特化

1
2
3
4
5
template <class T, class Allocator>
class vector { // … // };

template <class Allocator>
class vector<bool, Allocator> { //…//};

可变模板参数

这是C++11的新特性,支持模板的可变参数。可变模板参数的写法与原来有一点不同:

1
2
template <typename... T>
void f(T... args);

它需要在typename或者class后面加上省略号,带省略号的参数就是一个参数包,里面包含了0~N个参数。那么如何展开参数包呢?

两种方法

递归函数展开参数包

由于是递归调用,因此我们必须自定义递归的终止函数,保证其在参数为0时,停止递归。

1
2
3
4
5
6
7
8
9
10
11
12
//递归终止函数
void print()
{
cout << "empty" << endl;
}
//展开函数
template <class T, class ...Args>
void print(T head, Args... rest)
{
cout << "parameter " << head << endl;
print(rest...);
}

逗号表达式展开参数包

不表

C++11中的std::tuple就是一个可变参数模板类

参考资料

http://harttle.land/2015/10/03/cpp-template.html

http://www.cnblogs.com/qicosmos/p/4325949.html