Reputation: 217
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
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