【问题标题】:Add all parameters with parameter pack expansion [duplicate]使用参数包扩展添加所有参数[重复]
【发布时间】:2014-06-30 23:41:15
【问题描述】:

假设我有一个带有int... 参数的可变参数模板。例如这样的函数:

template<int... t>
int add(){
    return t... + ???
}

所有方法应该做的就是添加所有参数。使用递归可变参数模板可以轻松实现。但是,是否也可以使用参数包扩展来表达这一点(或类似使用其他二元运算符聚合所有模板参数)?

【问题讨论】:

  • 没有。只需按照可以轻松实现的方式进行即可。
  • 好的,我只是认为通过参数包扩展可能会更容易和更好地理解 :)
  • 其他解决方案的问题是它们计算执行时间的加法。
  • @Peregring-lk:你说得对,这是一个重要的事实!

标签: c++ templates c++11 variadic-templates


【解决方案1】:

是的,使用了我从休息室的@Xeo 那里学到的一个技巧。我最初用它来制作可变参数的“打印”模板函数。

#include <iostream>

template<int... ints>
int add()
{
  int result = 0;
  using expand_variadic_pack  = int[]; // dirty trick, see below
  (void)expand_variadic_pack{0, ((result += ints), void(), 0)... };
  // first void: silence variable unused warning
  // uses braced-init-list initialization rules, which evaluates
  //  the elements inside a braced-init-list IN ORDER, to repetetively
  //  execute a certain operation
  // second void is to prevent malicious "operator," overloads, which
  //  cannot exist for void types
  // 0 at the end is to handle empty variadic pack (zero-size array initializer is illegal.
  return result;
}

int main()
{
  std::cout << add<1,2,3,4>() << '\n';
}

这适用于所有支持 C++11 的编译器(GCC 4.8+、Clang 3.2+、MSVS2013、...)

【讨论】:

  • 不知道该笑还是该哭
  • @Lightness 你肯定曾经在 c++ 中滥用过表达式的副作用。
  • 当然! ??????
  • 这对auto a = {(ret += ints)... }; (void)a;也应该有效(并且看起来更干净)
  • @Peregring-lk 如果参数包为空,则初始化一个大小为零的数组,这是非法的。有关实际情况的更详尽解释,请参阅this answer
【解决方案2】:

一种使用 lambda 和 std::accumulate 的可能变体:

#include <array>
#include <numeric>

template <int... t>
int add()
{
    return [](const std::array<int, sizeof...(t)>& a)
    {
        return std::accumulate(a.begin(), a.end(), 0);
    }({t...});
}

【讨论】:

  • 这个看起来很干净,更不像黑客!不幸的是,计算不太可能在编译时得到优化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多