I don't understand the error message when trying to pass a variable number of initializer lists:
template<typename... Values>
void foo(Values...)
{
}
int main()
{
foo(1, 2, 3, "hello", 'a'); // OK
foo({1}, {2, 3}); // ERROR
}
The error message complains about too many arguments:
prog.cpp: In function ‘int main()’:
prog.cpp:9:20: error: too many arguments to function
‘void foo(Values ...) [with Values = {}]’
foo({1}, {2, 3});
^
prog.cpp:2:6: note: declared here
void foo(Values...)
^
However, should I not be able to pass as many arguments as I want? [ideone link]
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.
With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.
An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T .
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.
The problem is likely deducibility. {}
could be uniform initializers to any of the arguments.
This works:
#include <initializer_list>
template<typename... Values>
void foo(std::initializer_list<Values>... args)
{
}
template<typename... Values>
void foo(Values&&... args)
{
}
int main()
{
foo(1, 2, 3, "hello", 'a');
foo({1}, {2, 3});
}
See it Live on Coliru
The issue is not with the varadic arguments, but that the compiler cannot deduce the type of a brace enclosed initializer list, except for the case where you've declare the parameter of std::initializer_list<T>
§ 14.8.2.1 Template argument deduction is done by comparing each function template parameter type (call it P) with the type of the corresponding argument of the call (call it A) as described below. If removing references and cv-qualifiers from P gives std::initializer_list for some P0 and the argument is an initializer list (8.5.4), then deduction is performed instead for each element of the initializer list, taking P0 as a function template parameter type and the initializer element as its argument. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context (14.8.2.5).
There's even an example right below
template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T
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