C++——可变参数模板的分析

要理解可变参数模板的实现,需要先理解几个概念。

  • 参数包(包括模板参数包和函数参数包)
  • 展开参数包
  • 递归
template<typename T>
void print(T value)
{}

在上面的代码中,有两个参数列表。模板参数列表只包含T,函数参数列表只包含value,这里要说明的是模板参数列表是类型列表,函数参数列表是值列表。C++11提供了一个用省略号表示的元运算符,来声明参数包的标识符,如下。

template<typename... Args>
void print(Args... args)
{}

其中,Args是一个模板参数包,args是一个函数参数包,举个例子。

print(1, 2, 'a', "hello", 3.4);

当执行上面的调用时,模板参数包Args包含类型int、int、char、const char*、double,函数参数包args包含值1、2、‘a’、“hello”、3.4。
在函数中如何访问这些包中的内容呢?这些包并不是数组,所以不能像数组那样用下标访问,而是以展开包的方式访问(将省略号放在函数包的右边)。

template<typename... Args>
void print(Args... args)
{
	print(args...);
}

到这里,可变参数模板的实现只差一步了。可以发现上面的代码在被调用时进入了无限递归。解决办法是,将函数参数包展开,对列表中的第一项进行处理,再将余下的内容传递给递归调用,直至列表为空,新的定义如下。

template<typename T, typename... Args>
void print(T value, Args... args)
{
	cout << value << " ";
	print(args...);
}

上面的内容基本已经实现了可变参数模板。往往为了提高程序效率,不以值方式接收参数而是以引用方式接收参数。另外,对于多个参数而言,往往会对最后一个参数作特别的处理,同时,要考虑到没有参数传入的情况,最终的版本如下。

void print()
{}

template<typename T>
void print(const T& value)
{
	cout << value << endl;
}

template<typename T, typename... Args>
void print(T value, const Args&... args)
{
	cout << value << " ";
	print(args...);
}

当然,如果涉及到右值引用的问题,需要用到std::forward来保持右值引用类型的不变性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值