I feel a bit uncomfortable at the moment when using parameter packs. I've got a function
template <class ... Args>
void f( int x, Args ... args, int y )
{}
and of course using it like this works:
f( 5, 3 );
I am wondering why the following call fails:
f( 5, 3.f, 3 );
It seems like a straight-forward use of parameter packs to me, but according to the compiler Args
is not expanded.
Of course, I could easily replace f
by:
template <class ... Args>
void f( int x, Args ... args )
{
static_assert( sizeof...( args ) >= 1, ... );
extract y from args ...
}
Questions:
Why can't I use parameter packs like this? It seems like the compiler could easily create the replacement code. Or are there any problems with the replacement f()
above?
What is the best way to deal with this, if the order of the parameters is really important to me? (Think of std::transform
for an arbitrary number of input iterators.)
Why is the usage of parameter packs not forbidden in the situation above? I assume, it is because they could be expanded explicitly, e.g. f<float>( 5, 3.f, 3 )
?
Ellipsis in C++ allows the function to accept an indeterminate number of arguments. It is also known as the variable argument list.
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.
Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.
Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.
Why can't I use parameter packs like this? It seems like the compiler could easily create the replacement code. Or are there any problems with the replacement f() above?
Might be easy in this particular case, might not be in others. The real answer is that the Standard specifies the behavior and the Standard did not specify any transformation... and in general rarely does.
I would note that your transformation does not work with SFINAE, since static_assert
are hard-errors, so I am glad the transformation is not performed. (Hint: what if f
is overloaded with a single-argument version taking a float
, which would get chosen with/without transformation for f(1)
?)
What is the best way to deal with this, if the order of the parameters is really important to me? (Think of
std::transform
for an arbitrary number of input iterators.)
Explicitly specifying the template pack parameters.
Why is the usage of parameter packs not forbidden in the situation above? I assume, it is because they could be expanded explicitly, e.g. f( 5, 3.f, 3 )?
I think that your assumption is spot on; if explicitly specified this works as expected.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With