在C ++ 17之前的版本中模板参数包的“折叠”:惯用方法

时间:2019-10-28 09:51:17

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

C ++ 11和C ++ 14中的折叠式表达:惯用的方法吗?

问题与解答accepted answerVariadic template pack expansion使用通用的C ++ 17之前版本(在折叠表达式之前)对未扩展的模板参数包进行“折叠”。

我已经看到了这项技术的一些不同变化;以上述问答为例:

#include <initializer_list>
#include <iostream>
#include <utility>

template <typename T> static void bar(T) {}

template <typename... Args> static void foo1(Args &&... args) {
  using expander = int[];
  // Left-most void to avoid `expression result unused [-Wunused-value]`
  (void)expander{0, ((void)bar(std::forward<Args>(args)), 0)...};
}

template <typename... Args> static void foo2(Args &&... args) {
  int dummy[] = {0, ((void)bar(std::forward<Args>(args)), 0)...};
  // To avoid `unused variable 'dummy' [-Wunused-variable]`
  (void)dummy;
}

template <typename... Args> static void foo3(Args &&... args) {
  // Left-most void to avoid `expression result unused [-Wunused-value]`
  (void)std::initializer_list<int>{((void)bar(std::forward<Args>(args)), 0)...};
}

template <typename... Args> static void foo4(Args &&... args) {
  auto l = {0, ((void)bar(std::forward<Args>(args)), 0)...};
  // To avoid `unused variable 'l' [-Wunused-variable]`
  (void)l;
}

int main() {
  foo1(1, 2, 3, "3");
  foo1();
  foo2(1, 2, 3, "3");
  foo2();
  foo3(1, 2, 3, "3");
  foo3();
  foo4(1, 2, 3, "3");
  foo4();
  return 0;
}

这些变体(或其他变体)是否被视为“惯用的”?它们之间是否有任何细微之处/差异需要照顾?

std::initializer_list方法不需要在 braised-init-list 中最难以捉摸的0,因为初始化列表可能为空,而数组不能为零(负数)。可能这可能是foo3的一个论点(可以说,复杂度稍有降低,但需要额外的#include。)

1 个答案:

答案 0 :(得分:1)

  

这些变体(或其他变体)是否被视为“惯用的”?

我会说。

  

它们之间是否需要细微的区别?

大部分是等效的,但是

foo3foo4需要#include <initializer_list>
foo1foo2则没有。