“折叠” C ++ 17之前的模板参数包设置:惯用方法 [英] "Folding" of template parameter packs in pre C++17: idiomatic approach

查看:185
本文介绍了“折叠” C ++ 17之前的模板参数包设置:惯用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

接受的答案 Q& A的可变参数模板包扩展使用了常见的C ++之前版本17 (在折叠表达式之前)对未扩展的模板参数包进行折叠的方法。

The accepted answer of the Q&A Variadic template pack expansion makes use of a common pre-C++17 (prior to fold expressions) approach to "folding" of an unexpanded template parameter pack.

我见过这种技术的几种不同形式;以上面的Q& A为例:

I've seen a few different variations of this technique; taking the Q&A above as an example:

#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;
}

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

Are any of these variations (or other variations) considered "the idiomatic one"? Are there any subtleties/differences between them that one would need to take care with?

std :: initializer_list ,它们之间是否需要细微的区别?该方法不需要在 braced-init-list 中最难以捉摸的 0 ,因为初始化列表可能为空,而数组不得为零(负数)。可能这可能是 foo3 的一个论据(可以说,复杂度稍有降低,但需要额外的 #include )。 / p>

The std::initializer_list approach does not require the somewhat elusive left-most 0 in the braced-init-list, as an initializer list may be empty, whereas an array may not be zero(/negative)-sized. Possibly this could be an argument for foo3 (arguably slightly less complexity at the cost of an additional #include).

推荐答案


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

Are any of these variations (or other variations) considered "the idiomatic one"?

我会说是。


Are there any subtleties/differences between them that one would need to take care with?

大多数情况下,它们是等效的,但是

There are mostly equivalent equivalent, but

foo3 foo4 需要 #include< initializer_list>

,而 foo1 foo2 则没有。

foo3 and foo4 require #include <initializer_list>
whereas foo1 and foo2 don't.

这篇关于“折叠” C ++ 17之前的模板参数包设置:惯用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆