我正在写一个可变参数的求和函数(使用c ++ 20,但我的问题在c ++ 17语法中将保持不变)。我想使以下代码尽可能简短明了(但不使用折叠表达式。这只是一个玩具问题,但是在以后的应用程序中,我想避免使用折叠表达式):
Additive auto sum(Additive auto&& val, Additive auto&&... vals) {
auto add = [](Additive auto&& val1, Additive auto&& val2) {
return val1 + val2;
}; // neccessary??
if constexpr(sizeof...(vals) == 1) {
return add(val, std::forward<decltype(vals)>(vals)...); // (1)
//return val + std::forward<decltype(vals)>(vals)...; // (2)
}
else return val + sum(std::forward<decltype(vals)>(vals)...);
}
上面的代码使用第(1)行进行编译,但是它使“ add” lambda的定义成为必需。但是,第(2)行无法编译,使用gcc时出现以下错误:参数包未使用'...'扩展。如果在第(2)行的std :: forward表达式周围加上括号,则会出现以下错误:')'token之前的预期二进制运算符。
有什么方法可以将长度为1的参数包传递给运算符?
接受否定性思维的力量,从零开始而不是一开始归纳:
auto sum(auto &&val, auto &&...vals) {
if constexpr (sizeof...(vals) == 0)
return val;
else
return val + sum(std::forward<decltype(vals)>(vals)...);
}
上面的定义具有副作用,sum(x)
现在将进行编译和返回x
。(实际上,通过使该函数返回零,甚至可以使该函数不带任何参数,但是问题就来了:哪种类型为零?为避免去那里,我未定义此情况。)如果您坚持sum
仅从Arity 2向上定义,您可以改用以下方法:
auto sum(auto &&val0, auto &&val1, auto &&...vals) {
if constexpr (sizeof...(vals) == 0)
return val0 + val1;
else
return val0 + sum(std::forward<decltype(val1)>(val1),
std::forward<decltype(vals)>(vals)...);
}
但是,只要有必要,您就应该允许“空”情况:它使代码更简单,更通用。请注意,例如,在后一个定义中加法运算符是如何出现两次:这实际上是在两种情况之间复制了折叠逻辑(在这种情况下,它只是一个加法运算,因此相对简单,但操作更为复杂则可能会更麻烦) ,而处理简并的案例通常是微不足道的,并且不会重复任何事情。
(我省略了概念注释,因为它们似乎与主要问题并不特别相关。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句