高端知识点:折叠表达式(我也是第一次知道)

开发 后端
不知道大家以前了解折叠表达式不,这里介绍一下!我也是最近才知道这个知识点,在C++中通过折叠表达式可以更容易的在可变参数模板中处理可变参数。

[[411624]]

不知道大家以前了解折叠表达式不,这里介绍一下!

我也是最近才知道这个知识点,在C++中通过折叠表达式可以更容易的在可变参数模板中处理可变参数。

先看一下传统的使用递归方式来处理可变参数的代码:

  1. #include <iostream> 
  2.  
  3. void print(int i) { 
  4.     std::cout << i << " "
  5.  
  6. void func() {} 
  7.  
  8. template<typename T1, typename... Tn> 
  9. void func(T1 arg1, Tn... args) { 
  10.     print(arg1); 
  11.     func(args...); 
  12.  
  13. int main() { 
  14.     func(2, 3, 4); 
  15.     std::cout << "Hello World \n"

注意看代码里还需要有个不带参数的func()来停止递归。很麻烦!

而使用折叠表达式,通过单个函数模板就可以实现上述功能,不需要多余的函数,看代码:

  1. #include <iostream> 
  2.  
  3. void print(int i) { 
  4.     std::cout << i << " "
  5.  
  6. template<typename... T> 
  7. void func(const T&... args) { 
  8.     (print(args), ...); 
  9.     std::cout << "\n"
  10.  
  11. int main() { 
  12.     func(1, 2, 3); 
  13.     std::cout << "Hello World \n"

函数体中的三个点触发折叠。它会针对可变参数中的每个参数调用print(),对print()的每个调用用逗号分隔。

例如对于func(1, 2, 3),函数内的折叠表达式会展开成这样:

  1. (print(1), (print(2), print(3))); 

再用一个例子巩固下:

  1. #include <iostream> 
  2.  
  3. template<typename... T> 
  4. void func(const T&... args) { 
  5.     ((std::cout << args << " "), ...); 
  6.     std::cout << "\n"
  7.  
  8.  
  9. int main() { 
  10.     func(1, 2, 3); 
  11.     std::cout << "Hello World \n"

下面是折叠表达式展开后的形式:

  1. ((std::cout << 1<< " "), ((std::cout << 2 << " "), (std::cout << 3 << " "))); 

上面的示例中都是与逗号运算符结合使用,但实际上折叠可以和任何类型的运算符结合使用。例如与加号结合使用来计算所有值的和:

  1. #include <iostream> 
  2.  
  3. template<typename T, typename... Tn> 
  4. int sum(const T& v, const Tn&... values) { 
  5.     return (v + ... + values); 
  6.  
  7. template<typename... Tn> 
  8. int sum2(const Tn&... values) { 
  9.     return (... + values); 
  10.  
  11. int main() { 
  12.     std::cout << sum(1, 2, 3, 4) << "\n"
  13.     std::cout << sum2(1, 2, 3, 4) << "\n"
  14.     std::cout << "Hello World \n"

对于sum(1, 2, 3, 4),展开的形式如下:

  1. return (((1 + 2) + 3) + 4); 

但这里有个问题,该函数的使用一定需要至少一个参数,否则将无法通过编译:

  1. #include <iostream> 
  2.  
  3. template<typename T, typename... Tn> 
  4. int sum(const T& v, const Tn&... values) { 
  5.     return (v + ... + values); 
  6.  
  7.  
  8. int main() { 
  9.     sum(); 
  10.     std::cout << "Hello World \n"

报错如图:

长度为0其实也可以使用折叠表达式,但不能和加减这种运算符结合使用,只能和逻辑与、逻辑或和逗号结合使用。例如:

  1. #include <iostream> 
  2.  
  3. template <typename... Values
  4. double allTrue(const Values&... values) {  
  5.     return (... && values);  
  6.  
  7. template <typename... Values
  8. double anyTrue(const Values&... values) {  
  9.     return (... || values);  
  10.  
  11. int main() { 
  12.     std::cout << allTrue(1, 1, 0) << allTrue(1, 1) << allTrue() << "\n"; // 011 
  13.     std::cout << anyTrue(1, 1, 0) << anyTrue(0, 0) << anyTrue() << "\n"; // 100 

关于折叠表达式的介绍就到这里,打完收工!希望对大家有所帮助!

参考资料:

 

《Professional C++》

 

责任编辑:武晓燕 来源: 程序喵大人
相关推荐

2011-07-21 21:01:37

诺基亚塞班苹果

2021-02-05 08:35:21

私活程序员

2017-03-22 15:38:28

代码架构Java

2023-09-11 00:14:46

后端团队项目

2024-08-08 08:50:21

标签页portTab

2017-09-01 14:00:04

操作系统苹果OS X系统

2022-08-15 08:16:56

shiroWeb认证

2012-04-13 10:11:58

Windows 8泄露

2022-03-16 14:59:28

打包debian模板文件

2018-05-17 10:57:38

数据科学实习学习

2015-10-26 16:38:17

2022-06-21 09:26:28

开源项目PR

2022-12-28 08:03:02

Groovy语法GPath

2024-04-17 08:42:15

Go语言分布式锁

2021-07-28 15:28:22

JS逗号表达式面试题

2022-12-21 07:52:50

高并发架构扩容库

2017-08-08 12:50:51

Serverless云端数据库

2013-02-25 09:43:22

LambdasJava8

2018-08-15 10:34:30

戴尔

2018-11-21 14:51:00

Windows 功能系统
点赞
收藏

51CTO技术栈公众号