for_each_arg: Вызов функции для каждого аргумента функции

Вольный перевод статьи .

Как вызвать функцию для каждого аргумента другой функции?

Например, у нас есть функция

template<typename... Args>
void g(Args&&... args)
{
   // ...
}

и мы хотим применить некую функцию f к каждому аргументу функции g.

Требуется некий for_each_arg, который позволит выполнить следующее:

template<typename... Args>
void g(Args&&... args)
{
   for_each_arg(f, args...);
}

Как это решить с компилятором, не поддерживающим C++17?

Используем std::initializer_list, в список аргументов которого будем передавать результаты вызовов
f c аргументами args:
std::initializer_list<?>{(f(args))...}
Возникают проблемы:
1) Не знаем rvalue или lvalue передается в args - используем std::forward.
2) Какого типа элементы содержит std::initializer_list<?> . Допустим, что int, но функция f не обязана возвращать int,
3) поэтому приведем её возвращаемое значение к void и объединим оператором "запятая"  с целым 0.

В результате имеем: 

template<class F, class...Args>
F for_each_arg(F f, Args&&...args) {
  std::initializer_list<int>{((void)f(std::forward<Args>(args)), 0)...};
  return f;
}

Ну а с С++17 всё гораздо проще:

template<class F, class...Args>
F for_each_arg(F f, Args&&...args) {
  (f(std::forward<Args>(args)),...);
  return f;
}

Комментарии

Популярные сообщения из этого блога

Полезные новации С++17. Выражения свертки (Fold expressions)

Перегрузка и специализация шаблонных функций.

Ключевые слова auto и decltype – сходства, отличия и нюансы использования. Часть 3. decltype вывод типа сложного выражения.