C++函数模板可变参数如何一次性解包?

零、问题

如下代码中,调用func1的时候,只能递归一次取到一个值,有没有什么方法像func2中那样,一次把所有的值都拿出来呢?

回答

二元操作 (binary operator) 」 :需要两个操作数的操作,比如加法操作: a+b,再如输出流操作 : cout << 'a' ;二者分别对应 + 操作符和 << 操作符。

参数包 (parameter pack) 」: “正经”的函数模板的入参数是一个 伪类型,再加一个伪形参名,比如: T1 t1 。 参数包 则在二者中间加一个小三...,比如 T1 ... t1。

然后,C++17 的“二元操作”,支持其中一个使用 “参数包/pack”。编译器遇到二者,就会自动从“包”中取出一个参数,作为眼下就要进行的二元操作的一个操作数,进行操作。取参数次序还可以区分正序(从左到右排列)或倒序(从右到左排列)。

结合你要的例子:

template <typename T1, typename ...T2s> // #1
void func1(T1 a, T2s ... rest)          // #2
{
    std::cout << a;                     // #3
    (std::cout << ... << rest) << "\n";         // #4 rest:余下的
}

解读(示例方法,学会就能轻松阅读带 ... 的模板参数):

  • #1:typename 和 T1 之间干干净净,而 typename 和 T2s 之间夹着小三点,所以T1是一个正经的模板参数,但T2s是一个模板参数;它可能是0个或1个或更多个参数类型;
  • #2:T1和a之间干干净净,而T2 和 rest 之间夹着 小三点,所以 a 是一个参数,而 .. 和 rest 在此共同表示 一个包(参数包)。
  • #3:先是 std::cout 正经地输出了正经的入参 a;
  • #4:然后遇上参数包, “(cout << ... << rest)”,理解为 << (包中第1个参数);即首先从“包”中取眼下的第1个参数(如果有)作为 操作数2 ,与固定的操作数1(就是cout),进行 “<<” 运算——其实就是“输出”—— 然后,再取包中剩下的,如此反复,直至把参数包掏空。
  • 继续上一点:这里 “...” 和 具体的参数名(本例中的 rest )在语法与语义表达上有了分工:“...”表示包中的当前第一个,而 具名参数 rest 表示:“请继续如此处理包中余下的参数……”。另外 ,外围的括号( ) 是必须的,表示在 #4 这行完整的语句中,参与和参数包有关的求值的准确范围(一个表达式);所以 << "\n" 只会在参数包处理完成后执行只执行一次。事实上,哪怕把 << "\n" 从代码中删除,括号也得留着。

注:( ) 括号在C++中,早就不是可有可无的了,括号可强制令相关代码成为一个表达式。这点和 一元的 + (俗称正号)在某些地方,有和没有完全不同(有+号,会让修饰的代码变成表达式,典型如将一个 lambda 变成一个 表达式,最终转换成 函数指针的做法,以后有空再说)。

调用:

int main() 
{
    func1(12, " + ", 13, " == 25");
}

将输出: 12 + 13 == 25

或者给个空包:

func1("Hello world!"); // 形参 ... rest 是个空包

最后,支持的“原生”的二元操作符,共32个:

+ - * / % ^ & | = < > << >>

+= -= *= /= %= ^= &= |= <<= >>= == != <= >=

&& || , .* ->* 

作业:

来来来,写一个 my_sum( ) ,求一个多个数(整数或非整数)的累加和;要求不丢精。

/* 答题纸 */

答案:

template <typename T1, typename ... Rest>
auto my_sum(T1 n1, Rest ... rest)
{
    return (n1 + ... + rest);    
}

int main() 
{    
    std::cout << my_sum(1, 2, 3.3, 4, 5);
}

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南郁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值