Выразительные выражения в 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
).