C++变参模版

变参模版,即参数数目可变的模版,如printf()。声明变参函数时,需令函数参数列表包含一个省略号(...),变参模版也是如此:

template<typename ...ParameterTrack>
class my_template
{};

对于某个模版,即便其泛化版本的参数固定不变,也能用变参模版进行偏特化

(C++语法规定,任何模版必须具备泛化形式的声明,不能以偏特化形式声明,尽管泛化的packaged_task没有实际作用,其用途是告诉编译器存在名为packaged_task的模版):

template<typename FunctionType>	//无实际作用
class packaged_task;			//无实际作用
template<typename ReturnType, typename ...Args>
class packaged_task<ReturnType(Args...)>;

我们可以凭代码std::packaged_task<int(std::string, double)>声明一项任务,其以std::future<int>的实例给出结果,以std::string和double类型作为参数,其中变参列表可以为空。

特性:

1.普通模版参数(上例的ReturnType)和可变参数(上例的Args)能在同一声明内共存。

2.特化版本中使用了组合标记Args...,模版具现化时各型别依次列出。

3.模版实例化中,出现的型别被全部捕获并打包成Args,可变参数Args称为参数包(parameter pack),用“Args...”还原参数列表称为包的展开(pack expansion)。

展开参数包

在任何需要模版型别列表的场合,我们均可以直接运用展开式,在另一模版的参数列表中展开(展开模式省略号在后面),展开模式可随意设定复杂的型别表达式,前提是参数包在型别表达式中出现,且该表达式以省略号结尾:

template<typename ...Params>
class dummy
{
	std::tuple<std::string, Params...> data;
};

上面例子中,dummy类模版的参数在其tuple数据成员data的实例化中展开。
我们还可以依照某种模式创建元组,使其中的成员型别都是普通指针,甚至都是std::unique_ptr<>指针,目标型别对应参数包中的元素。

若模版参数列表用到了展开式,则模版无须再明文写出可变参数,参数包应准确匹配模版参数,所含参数数目必须相等:

template<typename ...Types>
struct dd
{
	std::pair<Types...> data;
};
dd<int, char> a;	//正确
dd<int> b;			//错误,缺少第二型别
dd<int, int, int> b;//错误,型别数过多

另一种用途是声明函数参数:

template<typename ...Args>
void func(Args ...args);

 一个函数的参数包还可以传递给另一个函数调用,后者在参数列表中设定好展开形式即可。以下例子通过std::forward<>保有函数参数的右值属性,“...”为展开位置

template<typename ...Args>
void bar(Args&& ...args)
{
	work(std::forward<Args>(args)...);
}
int i;
bar(i, 3.14, std::string("Circle"));

其展开形式为:

template<>
void bar<int&, double, std::string>(
	int& args_1,
	double&& args_2,
	std::string&& args_3)
{
	work(std::forward<int&>(args_1),
		 std::forward<double&&>(args_2),
		 std::forward<std::string&&>(args_3)
	);
}

第一项参数为以左值引用方式传入,余下参数则以右值引用传递。

我们可以通过sizeof...(p)运算符,确定参数包所含元素数目,其中p为参数包:

template<typename ...Args>
unsigned count_args(Args ...args)
{
	return sizeof...(Args);
}

sizeof...运算符求得的值是常量表达式,与普通sizeof运算符一样,故其结果可用于设定数组长度。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值