C++11 可变模板参数

前言

C++11 增强了模板功能,在C++11之前,类模板和函数只能含有固定数量的模板参数,现在C++11中的新特性可变参数模板允许模板定义中包含0到任意个模板参数。可变参数模板和普通模板的语义是一样的,只是写法上稍有区别,声明可变参数模板时需要在typename或class后面加上省略号“...”。其中的省略号的作用是:

(1)声明一个参数包,这个参数包中可以包含0到人一个模板参数

(2)在模板定义的右边,可以将参数包展开成一个一个独立的参数

1. 可变参数模板

一个可变参数模板的定义是这样的

template<class... T> void template_func(T... args)
{
    cout << sizeof...(args) << endl;
}

template_func(1);		//输出结果1
template_func(1, 2, 3);	//输出结果3
template_func(1, 2, "");	//输出结果3
从上面的例子可以看到,参数包可以容乃0到N个模板参数,这几个参数的类型可以任意的,在没有进行传参的时候,那么输出的结果就是0了。如果需要用参数包的参数,则一定要将参数包打开。有两种展开参数包的方法:

(1)通过递归的模板函数来实现参数包展开

(2)通过都好表达式和初始化列表方式展开参数包

1.1 递归函数方式展开参数包

通过递归函数展开参数包,需要提供一个参数包展开的函数和一个递归终止的函数,递归终止的函数正是用来终止递归的。

//递归展开参数包
template<class Q, class... T> void template_func(Q head, T... args)
{
	cout << "parameters:" << head << endl;
	template_func(args...); //递归展开参数包
}

//递归的终止函数
void template_func()
{
	cout << "end" << endl;
}

template_func(1, 2, 3, 4);
上面有两个函数,一个是递归函数一个是递归终止函数,参数包args...在展开自己的过程中递归调用自己,没吊用一次参数包中的参数就会减少一个,知道所有的参数都展开为止,当没有参数的之后,就调用递归终止函数结束。

也可将上面的非模板函数写成模板函数

//递归展开参数包
template<class K, class... T> void template_func1(K head, T ...args)
{
	cout << "parameters:" << head << endl;
	template_func1(args...); //递归展开参数包
}

//递归的终止函数
template<class T> void template_func1(T t)
{
	cout << t << endl;
}

template_func1(1,2,3,4);

1.2 逗号表达式和初始化列表方式展开参数包

递归函数展开参数包是一种标准做法,也比较好理解,但也存在一个缺点,就是必须要有一个重载的递归终止函数。使用逗号表达式和初始化列表就可以避免使用递归终止函数。

//展开参数包
template<class... T> void template_func1(T ...args)
{
	int array[] = {(my_print(args), 0)...};
}

template<class T> void my_print(T t)
{
	cout << t << endl;
}

template_func1(1,2,3,4);

2. 可变参数模板消除重复代码

可变参数模板的一个特性是参数包中的模板参数可以是任意数量的和任意类型的,因此,可以以一种更加返回的方式去处理一些问题。

下面是原始的创建对象工厂函数

template<typename T> T* Instance()
{
	return new T();
}

template<typename T,typename T0> T* Instance(T0 arg0)
{
	return new T(arg0);
}

template<typename T, typename T0, typename T1> T* Instance(T0 arg0, T1 arg1)
{
	return new T(arg0, arg1);
}

template<typename T, typename T0, typename T1, typename T2> T* Instance(T0 arg0, T1 arg1, T2 arg2)
{
	return new T(arg0, arg1, arg2);
}

struct A
{
	A(int a)
	{}
};

struct B
{
	B(int a, int b)
	{}
};

A* p_a = Instance<A>(1);
B* p_b = Instance<B>(1, 2);
修改之后

struct A
{
	A(int a)
	{}
};

struct B
{
	B(int a, int b)
	{}
};


template<typename T, typename... args> T* Instance(args... arg)
{
	return new T(arg...);
}

A* p_a = Instance<A>(1);
B* p_b = Instance<B>(1, 2);







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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值