C++11——可变参数模板

可变模板中,省略号的作用有两个:

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;
}

运行结果:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值