3

I would like to insert as many zeros into a vector as there are arguments to a variadic templated function (i.e. number of arguments zeros into a vector). I am trying to use fold expressions to achieve this and it works when using (vec.push_back(zeroHelper(args)), ...);.

What I do not understand: Why does it not work when I try to initialize the vector directly by "unfolding" into an initializer list like follows:
std::vector<int> vec = { (zeroHelper(args), ...) };?

Full source code:

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

And here's the source on OnlineGDB.

Expected output:

0
0
0
0

Output with the initializer list approach:

0

Why?

j00hi
  • 5,420
  • 3
  • 45
  • 82
  • why didn't you forward your elements to zero helper instead of copying l values from printer – asmmo Apr 08 '20 at 10:47
  • Following the advice of @asmmo, I got this: [**Demo on coliru**](http://coliru.stacked-crooked.com/a/e7ccbf679a86d7b6). (Parameter packs are not (yet) my strength. Hence, I became curious to puzzle this out.) – Scheff's Cat Apr 08 '20 at 11:08

1 Answers1

7

Because in

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

the parentheses return only one element, the last one; the comma operator discard the precedings.

You should write

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

to maintains all elements.

In

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

the parentheses activate the folding, the comma discards all elements except the last one but the push_back() operation is applied to vec for every args... elements.

Observe also that, using the discarding propriety of the comma operator, you don't need zeroHelper() at all

You can write

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

or

(vec.push_back(((void)args, 0)), ...);
max66
  • 65,235
  • 10
  • 71
  • 111
  • 1
    Hmm, `{ zeroHelper(args), ... }` does not work, it yields the error message "expected primary-expression before ‘...’ token". However, `{ zeroHelper(args) ... }` (without the comma) seems to work. – j00hi Apr 08 '20 at 10:43
  • 1
    @j00hi - yes, sorry: the comma is implicit in the `...` expansion. – max66 Apr 08 '20 at 10:47
  • @j00hi - answer improved with a couple of examples – max66 Apr 08 '20 at 10:53
  • Wow, didn't know about that discarding behaviour of the comma operator. I actually prefer the version without `zeroHelper`. Thanks a lot! – j00hi Apr 08 '20 at 10:59