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

pgpifvop  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(98)

C11和C14中的Fold-ish表达式:惯用法?

Q&A Variadic template pack expansion中的accepted answer使用了一种常见的C++17之前(在fold表达式之前)的方法来“折叠”未展开的模板参数包。
我见过这种技术的几种不同的变体;以上面的Q&A为例:

#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方法不需要 * 大括号初始化列表 * 中最左边的0,因为初始化列表可能是空的,而数组可能不是零(/负)大小。这可能是foo3的一个参数(可以说,以额外的#include为代价,复杂度略低)。

xwbd5t1u

xwbd5t1u1#

这些变体(或其他变体)中有没有被认为是“惯用的变体”?
我会说是的。
它们之间有什么微妙之处/区别需要注意吗?
大多数是等价的,但
foo3foo4需要#include <initializer_list>
foo1foo2则没有。

相关问题