C++17对可变长模板参数引入了折叠表达式,以简化对参数包的处理,也可以避免递归调用。
C++17前如果想实现一个可变长参数相加,需要这样实现:
#include <iostream>
using namespace std;
template<class T>
auto add(T t)
{
return t;
}
template<class T, class ...Args>
auto add(T t, Args... args)
{
return t + add(args...); //通过递归调用实现
}
int main()
{
cout<<add(1)<<endl; //输出:1
cout<<add(1, 2)<<endl; //输出:3
cout<<add(1, 2, 3)<<endl; //输出:6
cout<<add(1, 2, 3, 4)<<endl; //输出:10
return 0;
}
C++17的折叠表达式可以简化实现的方式:
#include <iostream>
using namespace std;
template <class ... Ts>
auto add(Ts ... ts)
{
return (... + ts); //折叠表达式
}
int main()
{
cout<<add(1)<<endl; //输出:1
cout<<add(1, 2)<<endl; //输出:3
cout<<add(1, 2, 3)<<endl; //输出:6
cout<<add(1, 2, 3, 4)<<endl; //输出:10
return 0;
}
折叠表达式支持 32 个操作符:?
+ | - | * | / | % | ^ | & | | | = | < | > | << | >> | += | -= | *= | /= | %= | ^= | &= | |= | <<= | >>= | == | != | <= | >= | && | || | .* | ->* | , | | | |
语法形式
折叠表达式共有四种语法形式。分别为一元的左折叠和右折叠,以及二元的左折叠和右折叠。
1.一元右折叠(unary right fold) ????????( pack op ... ) ????????一元右折叠(E op ...)展开之后变为 E1 op (... op (EN-1 op EN)) 2.一元左折叠(unary left fold) ????????( ... op pack ) ????????一元左折叠(... op E)展开之后变为 ((E1 op E2) op ...) op EN 3.二元右折叠(binary right fold) ????????( pack op ... op init ) ????????二元右折叠(E op ... op I)展开之后变为 E1 op (... op (EN?1 op (EN op I))) 4.二元左折叠(binary left fold) ????????( init op ... op pack ) ????????二元左折叠(I op ... op E)展开之后变为 (((I op E1) op E2) op ...) op EN
注: 1.语法形式中的op代表运算符,pack代表参数包,init代表初始值。
2.初始值在右边的为右折叠,展开之后从右边开始折叠。而初始值在左边的为左折叠,展开之后从左边开始折叠。
3.不指定初始值的为一元折叠表达式,而指定初始值的为二元折叠表达式。
4.当一元折叠表达式中的参数包为空时,只有三个运算符(&& || 以及逗号)有缺省值,其中&&的缺省值为true,||的缺省值为false,逗号的缺省值为void()。 ?
|