[C++11:可变参数的模板](https://blog.csdn.net/tennysonsky/article/details/77389891)
[泛化之美--C++11可变模版参数的妙用](https://www.cnblogs.com/qicosmos/p/4325949.html)
## [An introduction to C++'s variadic templates: a thread-safe multi-type map](https://jguegant.github.io/blogs/tech/thread-safe-multi-type-map.html#thread-safe-multi-type-map)
.
*****
## 可变参数模板函数的定义
```
#include <iostream>
using namespace std;
template<class ... T> void func(T ... args)
{//可变参数模板函数
//sizeof...(sizeof后面有3个小点)计算变参个数
cout << "num = " << sizeof...(args) << endl;
}
int main()
{
func(); // num = 0
func(1); // num = 1
func(2, 1.0); // num = 2
return 0;
}
```
## 参数包的展开
### 递归方式展开
通过递归函数展开参数包,需要提供一个参数包展开的函数和一个递归终止函数。
```
#include <iostream>
using namespace std;
//递归终止函数
void debug()
{
cout << "empty\n";
}
//展开函数
template <class T, class ... Args>
void debug(T first, Args ... last)
{
cout << "parameter " << first << endl;
debug(last...);
}
int main()
{
debug(1, 2, 3, 4);
return 0;
}
```
### 非递归方式展开
```
#include <iostream>
using namespace std;
template <class T>
void print(T arg)
{
cout << arg << endl;
}
template <class ... Args>
void expand(Args ... args)
{
int a[] = { (print(args), 0)... };
}
int main()
{
expand(1, 2, 3, 4);
return 0;
}
```
expand函数的逗号表达式:(print(args), 0), 也是按照这个执行顺序,先执行print(args),再得到逗号表达式的结果0。
同时,通过初始化列表来初始化一个变长数组,{ (print(args), 0)… }将会展开成( (print(args1), 0), (print(args2), 0), (print(args3), 0), etc…), 最终会创建一个元素只都为0的数组int a\[sizeof…(args)\]
# 可变参数模板类
## 继承方式展开参数包
可变参数模板类的展开一般需要定义2 ~ 3个类,包含类声明和特化的模板类:
```
#include <iostream>
#include <typeinfo>
using namespace std;
template<typename... A> class BMW{}; // 变长模板的声明
template<typename Head, typename... Tail> // 递归的偏特化定义
class BMW<Head, Tail...> : public BMW<Tail...>
{//当实例化对象时,则会引起基类的递归构造
public:
BMW()
{
printf("type: %s\n", typeid(Head).name());
}
Head head;
};
template<> class BMW<>{}; // 边界条件
int main()
{
BMW<int, char, float> car;
return 0;
}
```
## 模板递归和特化方式展开参数包
```
#include <iostream>
using namespace std;
template <long... nums> struct Multiply;// 变长模板的声明
template <long first, long... last>
struct Multiply<first, last...> // 变长模板类
{
static const long val = first * Multiply<last...>::val;
};
template<>
struct Multiply<> // 边界条件
{
static const long val = 1;
};
int main()
{
cout << Multiply<2, 3, 4, 5>::val << endl; // 120
return 0;
}
```
参考资料:[深入应用C++11 代码优化与工程级应用](http://pan.baidu.com/s/1kVsrgTx)
- C++基础
- 什么是 POD 数据类型?
- 面向对象三大特性五大原则
- 低耦合高内聚
- C++类型转换
- c++仿函数
- C++仿函数了解一下?
- C++对象内存模型
- C++11新特性
- 智能指针
- 动手实现C++的智能指针
- C++ 智能指针 shared_ptr 详解与示例
- 现代 C++:一文读懂智能指针
- Lamda
- c++11多线程
- std::thread
- std::async
- std::promise
- std::future
- C++11 的内存模型
- 初始化列表
- std::bind
- std::tuple
- auto自动类型推导
- 可变参数模板
- 右值引用与移动语义
- 完美转发
- 基于范围的for循环
- C++11之POD类型
- std::enable_if
- C++14/17
- C++20
- 协成
- 模块
- Ranges
- Boost
- boost::circular_buffer
- 使用Boost.Asio编写通信程序
- Boost.Asio C++ 网络编程
- 模板
- 模板特化/偏特化
- C++模板、类模板、函数模板详解都在这里了
- 泛化之美--C++11可变模版参数的妙用
- 模板元编程
- 这是我见过最好的模板元编程文章!