操作员旁边的参数解包

阿德尔哈特

我正在写一个可变参数的求和函数(使用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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章