Как расширить список инициализаторов с помощью выражений свертки? - PullRequest
0 голосов
/ 08 апреля 2020

Я бы хотел вставить в вектор столько нулей, сколько имеется аргументов для шаблонной функции c (т.е. количество аргументов нулей в векторе). Я пытаюсь использовать выражения сгиба для достижения этой цели, и это работает при использовании (vec.push_back(zeroHelper(args)), ...);.

Что я не понимаю: почему это не работает, когда я пытаюсь инициализировать вектор напрямую, «развернув» в Список инициализаторов выглядит следующим образом:
std::vector<int> vec = { (zeroHelper(args), ...) };?

Полный исходный код:

template <typename T>
T zeroHelper (T a) { return T{0}; }

template<typename ...Args>
void printer(Args&&... args) {
    std::vector<int> vec; // = { (zeroHelper(args), ...) };
    (vec.push_back(zeroHelper(args)), ...);
    for (auto i : vec) {
        std::cout << i << '\n';
    }
}

int main()
{
    printer(1, 2, 3, 4);
    return 0;
}

А вот источник на OnlineGDB.

Ожидаемый вывод:

0
0
0
0

Вывод с использованием подхода списка инициализаторов:

0

Почему?

1 Ответ

5 голосов
/ 08 апреля 2020

Поскольку в

std::vector<int> vec = { (zeroHelper(args), ...) };

круглые скобки возвращают только один элемент, последний; оператор запятой отбрасывает предыдущее.

Вы должны написать

std::vector<int> vec = { zeroHelper(args) ... };

, чтобы сохранить все элементы.

В

(vec.push_back(zeroHelper(args)), ...);

скобки активируют При сворачивании запятая отбрасывает все элементы, кроме последнего, но операция push_back() применяется к vec для каждого args... элемента.

Также обратите внимание, что, используя свойство отбрасывания оператора запятой, вы zeroHelper() вообще не нужно

Вы можете написать

std::vector<int> vec { ((void)args, 0)... };

или

(vec.push_back(((void)args, 0)), ...);
...