变参模板4:折叠表达式
题目描述
折叠表达式允许在参数包中连续“折叠”地做二元运算,并得到一个最终的结果。比如对于形参包 1, 2, 3, 4
,在其上左折叠地做“加法”,效果就如同 (((1+2)+3)+4)
。类似地还有右折叠,只不过是先对最后两个形参做运算。
左折叠的折叠表达式写成 (... op args)
,其中 op
是二元运算符,args
是形参包,如 (... + args)
就是左折叠地做加法。右折叠就是将省略号放在运算符右侧:(args op ...)
。注意折叠表达式的外围括号是必需的。
折叠表达式既可以作用在函数形参包上,也可以作用在模板形参包上。比如对于 template <int... Ns> /* ... */
这种模板,出现 (... * Ns)
的场合就会被替换为所有 Ns
非类型实参的乘积。
下面请实现函数模板 sum
返回所有实参的和、函数模板 sumOfSquare
返回所有实参的平方和、类模板 Sum
具有静态常量成员 value
以计算模板实参的和。
注:很显然这种折叠要求形参包的形参个数必须大于等于 2。对于数量更少的形参包,可以用带初始值的折叠表达式,写成 (init op ... op args)
或 (args op ... op init)
。这道题目对这种形式不做考察,所以这里只是简单介绍一下。
关于输入
无
关于输出
见样例输出
参考答案
#include <iostream>
#include <string>
template <typename... Ts>
auto sum(Ts... ts) {
return (... + ts);
}
template <typename... Ts>
auto sumOfSquare(Ts... ts) {
return (... + (ts * ts));
}
template <int... Ns>
struct Sum {
static constexpr int value = (... + Ns);
};
int main() {
std::cout << sum(6, 6, 6) << std::endl;
std::cout << Sum<1, 2, 3, 4, 5>::value << std::endl;
std::cout << sum(1, 4, 2, 8, 5, 7) << std::endl;
std::cout << Sum<4, 3, 9, 9>::value << std::endl;
std::cout << sum(std::string{}, "Hello", ", ", "world", '!') << std::endl;
std::cout << sumOfSquare(3, 4, 12, 13) << std::endl;
}