[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可變模版參數的妙用
- 模板元編程
- 這是我見過最好的模板元編程文章!