精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
服务方向
联系方式
锐英源精品原创,禁止转载和任何形式的非法内容使用,违者必究。点名“简易百科”和“闲暇巴”盗用锐英源原创内容。
C++17折叠表达式简化了循环计算多个值或变量处理,...代表了N个值或变量,让循环计算简单且易懂,让算法开发更简单,特别是矩阵的行列数据数据计算。改进建议是能支持数组或容器内项的计算,让数组和容器内的项自动进行计算,这样更强大。
以前看过Python的数据结构处理,非常方便,虽然希望C++能够学习,不过也要看现实,毕竟数据结构类型越大,编译器就越麻烦,这和C++性能第一的目标有些相背。
C++17 标准引入了语言语法的一个新元素 - 折叠表达式。这种新语法用于折叠可变参数模板参数包(可变参数模板获取可变数量的参数,自 C++11 起受 C++ 支持)。使用 folding 有助于避免繁琐的递归调用,并允许我们以紧凑的形式将操作应用于 pack 的所有单个参数。在处理模板参数包列表时,折叠表达式可以与以下二元运算符一起使用:+、-、*、/、%、^、&、|、=、<、>、<<、>>、+=、-=、*=、/=、%=、^=、&=、|=、<<=、>>=、==、!=、<=、>=、&&、||、,, .*、->*。
使用可变参数模板声明 fold 表达式的语法:
template<class... T>
decltype(auto) summation(T... Values)
{
// unfolds into the expression Values1 + (Values2 + (Values3 + Values4))...
return (Values + ...);
}
让我们看一下以下示例:
#include <iostream>
#include <string>
template <typename ... Ts>
auto Sum_RightHand(Ts ... ts)
{
return (ts + ...);
}
template <typename ... Ts>
auto Sum_LeftHand(Ts ... ts)
{
return (... + ts);
}
int main() {
std::cout << "Sum_RightHand output: \n";
std::cout << Sum_RightHand(10, 20, 30) << std::endl;
std::cout << Sum_RightHand(1.5, 2.8, 3.2) << std::endl;
std::cout << Sum_RightHand(std::string("Hi "), std::string("standard "),
std::string("C++ 17")) << std::endl;
std::cout << "\n";
std::cout << "Sum_LeftHand output: \n";
std::cout << Sum_LeftHand(10, 20, 30) << std::endl;
std::cout << Sum_LeftHand(1.5, 2.8, 3.2) << std::endl;
std::cout << Sum_LeftHand(std::string("Hi "), std::string("standard "),
std::string("C++ 17")) << std::endl;
return 0;
}
在上面的代码中,对于这两个函数,我们使用模板参数 pack 定义了签名:
模板 <typename ...Ts>
auto function_name (Ts ...ts)
函数展开所有参数并使用 fold 表达式对它们进行汇总。(在函数范围内,我们使用 +运算符应用于参数包的所有值)
正如我们所看到的,Sum_RightHand (ts + ...)和Sum_LeftHand (... + ts)给出相同的结果。但是,它们之间存在差异,这在其他情况下可能很重要:如果省略号 (...) 位于运算符的右侧,则表达式称为右折叠。如果它在左侧,则它是左侧折叠。
在我们的示例中, 展开如下:Sum_LeftHand
10 + (20 + 30)
1.5 + (2.8 + 3.2)
"嗨" + ("标准 " + "C++ 17")
右一元折叠 with 展开如下:Sum_RightHand
(10 +20) + 30
(1.5 + 2.8) + 3.2
("Hi" + "standard ") + "C++ 17"
这些函数适用于不同的数据类型:int 、double 、 和std::string ,但可以为实现 +运算符的任何类型的函数调用它们。
在上面的例子中,我们向两个函数传递了一些参数来获得求和的结果。但是,如果我们调用没有参数的函数会发生什么呢?
例如,如下所示:
C++
int main() {
std::cout << Sum_RightHand() << std::endl;
return 0;
}
Sum_RightHand ()函数调用时不带参数的,任意长度的参数包将不包含可以折叠的值,这会导致编译错误。
要解决这个问题,我们需要返回一个特定的值。一个明显的解决方案是返回零。
所以我们可以像这样实现它:
C++
#include <iostream>
#include <string>
template <typename ... Ts>
auto Sum_RightHand(Ts ... ts) {
return (ts + ... + 0);
}
template <typename ... Ts>
auto Sum_LeftHand(Ts ... ts) {
return (0 + ... + ts);
}
int main() {
std::cout << "Sum_LeftHand() = " << Sum_LeftHand() << std::endl;
std::cout << "Sum_RightHand() = " << Sum_RightHand() << std::endl;
return 0;
}
请注意,这两个 fold 表达式都使用初始值 ZERO!当没有参数时,中性元素非常重要 - 在我们的例子中,将任何数字添加到 0 都不会改变任何内容,使 0 成为中性元素。因此,我们可以使用+ or -运算符添加0到任何折叠表达式中。如果参数 pack 为空,这将导致函数返回值0 。从数学的角度来看,这是正确的,但在实现方面,我们需要根据我们的要求确定什么是正确的。