«Сворачивание» пакетов параметров шаблона в до C ++ 17: идиоматический подход - PullRequest
1 голос
/ 28 октября 2019

Выразительные выражения в C ++ 11 и C ++ 14: идиоматический подход?

принятый ответ из Q & A Расширение пакета шаблонов Variadic делаетиспользование общего подхода, предшествующего 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 не требует несколько неуловимого самого левого 0 в списке braced-init-list, поскольку список инициализаторов может быть пустым, тогда как массив не может иметь нулевой (/ отрицательный) размер. Возможно, это может быть аргументом для foo3 (возможно, немного меньшей сложности за счет дополнительных #include).

1 Ответ

1 голос
/ 28 октября 2019

Любой из этих вариантов (или других вариантов) считается "идиоматическим"?

Я бы сказал, да.

Есть ли какие-то тонкости/ различия между ними, о которых нужно было бы позаботиться?

В основном это эквивалентные эквиваленты, но

foo3 и foo4 требуют #include <initializer_list>
, тогда какfoo1 и foo2 нет.

...