【可变参模板】折叠表达式

折叠表达式 ( F o l d   E x p r e s s i o n s ) (Fold \ Expressions) (Fold Expressions) C + + 17 C++17 C++17标准引入的,引入折叠表达式的主要目的是计算某个值(表达式的结果当然是一个值)。这个值的特殊在于:
它与所有可变参有关,而不是与但单独某个可变参有关。
由于可变参的展开比较繁琐,所以使用折叠表达式,可以不展开参数而计算出可变参的结果。

一、一元左折 ( U n a r y   L e f t   F o l d ) (Unary\ Left\ Fold) (Unary Left Fold)

格式:(…运算符 一包参数)
计算方式:((参数1 运算符 参数2)运算符 参数3…)

一元左折的计算是从最左边开始的,不断向左折叠

注意的是,折叠表达式都需要加上括号,以下不在赘述。

下面是一元左折的简单使用:

//一元左折
template<typename... T>
int add_left(T... args) {
	return (... + args); //不能省略括号

}

template<typename... T>
int del_left(T...args) {
	return (... - args);
}

调用下面的函数

void Test1() {
	std::cout << add_left(10, 20, 30) << "\n";

	std::cout << del_left(10, 20, 30) << "\n";

}

得到结果为:
在这里插入图片描述

可以验证发现运算顺序如上文描述一样。

二、一元右折 ( U n a r y   R i g h t   F o l d ) (Unary\ Right\ Fold) (Unary Right Fold)

格式:(一包参数 运算符…)
计算方式:(参数1 运算符(…(参数n-1 运算符 参数n)) )

一元右值的计算是从最右边开始的,不断向右折叠

下面是一元右折的使用:

template<typename... T>
int del_left(T...args) {
	return (... - args);
}

void Test1() {
	std::cout << add_left(10, 20, 30) << "\n";

	std::cout << del_left(10, 20, 30) << "\n";

}

//一元右折
template<typename ...T>
int del_right(T...args) {
	return (args - ...); //注意参数中...的位置
}

void Test2() {
	std::cout << del_right(10, 20, 30) << "\n";
}

运行后,得到:

在这里插入图片描述
这个运算顺序,显然是:
( 10 − ( 20 − 30 ) ) = 10 − ( − 10 ) = 20 (10-(20-30)) = 10 - (-10) = 20 (10(2030))=10(10)=20
符合一元右折的计算规律。

三、二元左折 ( B i n a r y   L e f t   F o l d ) (Binary\ Left\ Fold) (Binary Left Fold)

二元左折和一元左折的区别就是,二元左折可以传入自定义的 i n i t init init初始值参与计算。

格式:( i n i t init init 运算符 … 运算符 一包参数)
计算方式:((( i n i t init init 运算符 参数1)运算符 参数2 )… 运算符 参数N)

二元左折的使用如下:
这里,二元左折还能使用一个支持运算符的对象,比如这里使用的是 c o u t cout cout对象:

//二元左折
template<typename... T>
int del_left_b(T...args) {
	return (100 - ... - args); //参数为数值
}

template<typename... T>
void print(T...args) {
	(std::cout << ... << args);  //参数为cout
}

void Test3() {
	std::cout << del_left_b(10, 20, 30) << "\n";
	print(1, "abc", 1.2, 'x');
}

调用结果如下:
在这里插入图片描述

四、二元右折 ( B i n a r y   R i g h t   F o l d ) (Binary\ Right\ Fold) (Binary Right Fold)

二元右折和二元左折类似,在格式和计算方式上不同:

格式:(一包参数 运算符 … 运算符 init)
计算方式(参数1 运算符(…(参数N 运算符 init)))

下面是使用二元右折的例子:

//二元右折
template<typename... T>
int del_right_b(T...args) {
	return (args - ... - 100);
}

void Test4() {
	std::cout << del_right_b(10, 20, 30) << "\n";
}

结果如下:
在这里插入图片描述

五、可变参表达式

当然,如果我们想对每个传入的参数进行 ∗ 2 *2 2操作,然后再累加后输出每一项的结果呢,这时我们就需要写一个可变参表达式,使用折叠表达式来计算最终的结果,还需要一个中间模板来传递 2 ∗ a r g s 2*args 2args的信息。

模板如下:

//可变参表达式
template<typename... T>
auto print_result(T const&... args) {
	(std::cout << ... << args) << "结束\n"; //注意括号是必要的
	return (... + args); //一元左折
}

template<typename...T>
void print_calc(T const&... args) {
	std::cout << print_result(2 * args...) << "\n";
}

调用下面代码:

void Test5() {
	print_result(1, 2, 3, 4, 5); 

	print_calc(1, 2, 3, 4, 5);
}

运行结果为:

在这里插入图片描述

我们成功得到了每个数 ∗ 2 *2 2的单独的结果,并且得到了累加后的总和。

注意下面几个写法:

//错误
print_result(args *2); 
print_result(args...*2); 
print_result(args * 2...); 
print_result(2* args); 

//正确
print_result(args * 2 ...);
print_result((args * 2) ...); 
print_result(2 * args ...); 
print_result((2 * args) ...); 
print_result((args+args) ...); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值