觉得自己还是需要好好去学一门编程语言,嗯,就C++吧
折叠表达式简介
C++11提供了可变模板参数包,使函数可以接受任意数量的参数。但在C++11中展开参数包稍显麻烦,而 C++17 的折叠表达式使得展开参数包变得容易, 其基本语法是使用 (…) 的语法形式进行展开。
折叠表达式支持的操作符:
+, -, *, /, %, ^, &, |, =, <,
>, <<, >>, +=, -=, *=, /=, %=, ^=, &=, |=, <<=,
>>=,==, !=, <=, >=, &&, ||, ,, .*, ->*.
一元折叠示例
折叠分类:左折叠和右折叠
// 右折叠
template<typename ... T>
auto sum_right(T ... t) {
return (t + ...);
}
// 左折叠
template<typename ... T>
auto sum_left(T ...t) {
return (... + t);
}
int main()
{
std::cout << sum_left(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << std::endl;
return 0;
}
左折叠反汇编:
00007FF6F44749BC 8B 85 E8 00 00 00 mov eax,dword ptr [<t_1>]
00007FF6F44749C2 8B 8D E0 00 00 00 mov ecx,dword ptr [<t_0>]
00007FF6F44749C8 03 C8 add ecx,eax
00007FF6F44749CA 8B C1 mov eax,ecx
00007FF6F44749CC 03 85 F0 00 00 00 add eax,dword ptr [<t_2>]
00007FF6F44749D2 03 85 F8 00 00 00 add eax,dword ptr [<t_3>]
00007FF6F44749D8 03 85 00 01 00 00 add eax,dword ptr [<t_4>]
00007FF6F44749DE 03 85 08 01 00 00 add eax,dword ptr [<t_5>]
00007FF6F44749E4 03 85 10 01 00 00 add eax,dword ptr [<t_6>]
00007FF6F44749EA 03 85 18 01 00 00 add eax,dword ptr [<t_7>]
00007FF6F44749F0 03 85 20 01 00 00 add eax,dword ptr [<t_8>]
00007FF6F44749F6 03 85 28 01 00 00 add eax,dword ptr [<t_9>]
显然左折叠类似于这种结合的方式进行执行
(((1 + 2) + 3) + 4) + 5
右折叠则相反
二元折叠示例
前例中如果参数是空的,则会报错,可以通过加上一个数值0(缺省值)来解决编译错误,这就变成了二元折叠
示例:
template<typename ... T>
auto sum_right(T ... t) {
return (t + ... + 0);
}
template<typename ... T>
auto sum_left(T ...t) {
return (0 + ... + t);
}
这样一来,即便函数给的参数是空的,也能正常执行编译不报错了
空参数包就是参数包中不含任何参数。
对于大多数操作符,空参数包将会引发编译错误。
对于 && 或 ||,空参数包是合法的,其中 && 的展开结果为 true,||
的展开结果为 false。在逗号 , 操作符中,空参数包也合法,展开为 void()。
示例
计算指定集合内包含指定数值的个数
template<typename R ,typename ...T>
auto count(const R& range, T...t) {
return (std::count(std::begin(range), std::end(range), t) + ... + 0);
}
int main()
{
std::vector<int> scores = { 1,2,3,4,5,6,7,8,9,10};
std::cout << count(scores,3,5,7) << std::endl; // 3
std::cout << count("hello world",'o','l') << std::endl; // 5
return 0;
}
这是右折叠的方式进行函数调用,就是对参数中最右边两个数进行指定运算,结果与从右边起的下一个数继续进行运算,而进行的运算就是这里()
里指定的对...
的模板参数进行的运算,这里就是std::count(std::begin(range), std::end(range), t) + ...
,就是对每一个t都进行这个运算然后都相加
连续打印不同类型的值
template<typename...T>
auto sel_dbgprint(T...t) {
(std::cout << ... << t) << std::endl;// 折叠表达式需要放在小括号里使用
}
int main()
{
sel_dbgprint("ERROR::",250,"::妙啊");
return 0;
}
参考资料:
- [1] [C++17 折叠表达式 | Greedysky’s Blog](https://greedysky.github.io/2020/12/01/C++17 折叠表达式/)
- [2] 第 2 章 语言可用性的强化 现代 C++ 教程: 高速上手 C++ 11/14/17/20 - Modern C++ Tutorial: C++ 11/14/17/20 On the Fly (changkun.de)
- [3] C++17折叠表达式的用法_C++yyds~~~的博客-CSDN博客