Flying Hat
Flying Hat

Reputation: 217

Calling a function inside an initializer list with an empty parameter pack function argument

I have

void foo(double &arg, uint8_t *data)
{
    // ...
}

template <class T>
void foo(T &arg, uint8_t *data)
{
    // ...
}

and I call it in

template <class ...T>
void bar(T... arg)
{
    uint8_t *data = new uint8_t[SOME_VALUE];

    // guaranteed to be executed in order
    auto list = {(foo(arg, data), 1)...};

   // ...
}

But it fails when bar is called with 0 arguments, because of the way foo is called in the initializer list.

How can I modify this to make bar work with an empty parameter pack? The result should be as if the initializer list has never executed.

I'd like to keep the foo application iterative, i.e. with the initializer list in bar, rather than recursive, when we do a single call to foo in bar and the variadic-template foo calls itself until its parameter pack is empty. (Mostly because the latter seems to be costly -- the stack falls through quite a lot when the pack has many arguments and it causes a lot of different template versions of foo to be generated.)

Upvotes: 0

Views: 120

Answers (1)

T.C.
T.C.

Reputation: 137315

Basically, the problem is that auto list = {}; doesn't work.

Either specify the type explicitly:

std::initializer_list<int> list = {(foo(arg, data), 1)...};

or give it an extra element:

auto list = {1, (foo(arg, data), 1)...};

Side note: for fully generic code, when you don't know the return type of foo, you'd want to cast the return value of foo to void, to defend against possibly overloaded comma operators.

Upvotes: 5

Related Questions