可变模板中,省略号的作用有两个:
1.声明一个参数包T... args,这个参数包中可以包含0到任意个模板参数;
2.在模板定义的右边,可以将参数包展开成一个一个独立的参数;
// std::template 可变参数模板
//可变模板中,省略号的作用有两个:
//1.声明一个参数包T... args,这个参数包中可以包含0到任意个模板参数;
//2.在模板定义的右边,可以将参数包展开成一个一个独立的参数;
class CTemplate : public CBase
{
public:
CTemplate() { }
virtual ~CTemplate() {}
virtual void Run();
//eg1 可变参数模板1
template <class... T>
void Func(T... args)
{
printf("[std::template] args: %d \n", sizeof...(args)); //打印变参的个数
}
//eg2 递归函数展开参数包
template <class T, class ...Args>
void Print(T head, Args... rest)
{
cout << "[std::template] parameter: " << head << endl;
Print(rest...); //递归终止函数
}
//递归终止函数
void Print(){ cout << "[std::template] Print: empty" << endl; }
//eg3 递归函数展开参数包 求和
template<typename T>
T Sum(T t){ return t; }
template<typename T, typename ... Types>
T Sum(T head, Types ... rest)
{
return head + Sum<T>(rest...);
}
//eg4 递归函数展开参数包(必须要一个重载的递归终止函数,解决方案:借助逗号表达式和初始化列表)
template <class T>
void PrintArg(T t){ cout << "[std::template] PrintArg: " << t << endl; }
template <class ...Args>
auto Expand(Args... args)
{
// 数组 int arr[sizeof...(Args)]
int arr[] = { (PrintArg(args), 0)... }; //展开式((PrintArg(arg1),0), (PrintArg(arg2),0), (PrintArg(arg3),0), etc... )
return std::accumulate(&arr[0], &arr[_countof(arr) - 1], 0);
}
// eg5 将函数作为参数,支持lambda表达式,可以少写一个递归终止函数
template<class F, class... Args>
void expand(const F& f, Args&&...args)
{
//initializer_list 某种特定类型的值的数组,一种模板类型, 完美转发
std::initializer_list<int> { (f(std::forward< Args>(args)), 0)... };
}
// eg6 可变参数模板 加法
template<typename T, typename ... Args>
int Add(T num, Args... args)
{
int res = 0;//结果
va_list argp; //存储参数开始的地址
va_start(argp, num); //从首地址开始,读取num后面的数据
for (int i = 0; i < num; i++)
{
//读取一个数据并且按照int类型进行二进制数据的解析
//然后读取下一个数据
res += va_arg(argp, int);
}
va_end(argp);//结束读取
return res;
}
};
void CTemplate::Run()
{
printf("========std::template==========\n");
//C++11中的元组 std::tuple 就是一个可变模板类
std::tuple<int> tp1 = std::make_tuple(1);
std::tuple<int, double> tp2 = std::make_tuple(1, 2.5);
std::tuple<int, double, string> tp3 = std::make_tuple(1, 2.5, "");
Func(); //0
Func(1, 2); //2
Func(1, 2.5, ""); //3
Print(1, 2, 3, 4);
auto nVal = Sum(1, 2, 3, 4);
cout << "[std::template] Sum: " << nVal << endl;
//Expand(1, 2, 3, 4);
cout << "[std::template] Expand<sum>: " << Expand(1, 2, 3, 4) << endl;
expand([](int i)
{
cout << "[std::template] expand: " << i << endl; }, 1, 2, 3
);
//加入lambda表达式
expand([](auto i) {cout << "[std::template] expand: " << i << endl; }, 1, 2.0, "test");
// 标准模板加法
int nRes = Add(4, 1, 2, 3, 4);
cout << "[std::template] Add<nRes>: " << nRes << endl;
}
调用:
// C++11Demo.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <time.h>
#include <thread>
#include "Function.h"
#include <iomanip>
#include <iostream>
#define Tab printf("\n");
int main()
{
std::shared_ptr<CBase> pTemplate = std::make_shared<CTemplate>();
pTemplate->Run(); Tab;
return 0;
}
运行结果: