C++17中的Fold Expression

C++11中增加了一个新特性可变模版参数(variadic template),它可以接受任意个模版参数在参数包中,参数包是三个点…,它不能直接展开,需要通过一些特殊的方法才能展开,导致在使用的时候有点难度。现在C++17解决了这个问题,让参数包的展开变得容易了,Fold expression就是方便展开参数包的。

fold expression的语义

fold expression有4种语义:

其中pack代表变参,比如args,op代表操作符,fold expression支持32中操作符:

unary right fold的含义:

fold (E op …) 意味着 E1 op (… op (EN-1 op EN)).
顾名思义是从右边开始fold,我们来看一个具体的例子:

right fold的过程是这样的:(1+(2+(3+4))),从右边开始fold。

unary left fold的含义

fold (… op E) 意味着 ((E1 op E2) op …) op EN.

对于+这种满足交换律的操作符来说left fold和right fold是一样的,比如上面的例子你也可以写成left fold。

对于不满足交换律的操作符来说就要注意了,比如减法。

这次right fold和left fold的结果就不一样。

binary fold

Binary right fold (E op … op I) 意味着 E1 op (… op (EN-1 op (EN op I)))

Binary left fold (I op … op E) 意味着 (((I op E1) op E2) op …) op E2

二元fold的语义和一元fold的语义是相同的,看一个二元操作符的例子:

相信通过这个例子大家应该对C++17的fold expression有了基本的了解。

comma fold

在C++17之前,我们经常使用逗号表达式和std::initializer_list来将变参一个个传入一个函数。比如像下面这个例子:

这种写法比较繁琐,用fold expression就会变得很简单了。

这是right fold,你也可以写成left fold,对于comma来说两种写法是一样的,参数都是从左至右传入print_arg函数。

fold expression操作符的默认值

需要注意的是fold expression有三个操作符有默认值:

测试一下默认值:

通过这些例子可以看到fold expression确实简化了可变模版参数的展开,用起来更简单更灵活,可以基于fold expression写出更多优雅的代码,fold expression也增强了变参的威力。

发表评论

Copy Protected by Chetan's WP-Copyprotect.