I already know the stdarg.h
way to have a function with variable arguments in c++ as discussed here for example.
I also know c++11 standard has variadic templates as explained here.
But in both of aforementioned schemes we don't know (and we can't force) argument types in compile time afaik. What I'm looking for is to pass variable arguments of known types to a function. I think this can be done because I read about it here:
Variadic templates, which can also be used to create functions that take variable number of arguments, are often the better choice because they do not impose restrictions on the types of the arguments, do not perform integral and floating-point promotions, and are type safe.
Is it possible? If yes, how can I do this?
To call a function with a variable number of arguments, simply specify any number of arguments in the function call. An example is the printf function from the C run-time library. The function call must include one argument for each type name declared in the parameter list or the list of argument types.
In mathematics and in computer programming, a variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments.
A variable argument function (variadic function) is a function that can accept an undefined number of arguments. In many programming languages, formatted output functions are defined as variadic functions. In C++, variable argument functions are declared with the ellipsis (...) in the argument list field.
Neither the C nor C++ standard places an absolute requirement on the number of arguments/parameters you must be able to pass when calling a function, but the C standard suggests that an implementation should support at least 127 parameters/arguments (§5.2.
It is straight forward to write a function with variadic templates, that accept an arbitrary number of arguments. The only difference to the general pattern is, that a concrete type is used as first argument (head) - instead of a template parameter. The following example shows a function foobar
, that accepts an arbitrary number of strings.
// used for end of recursion - and for the empty arguments list
void foobar() { }
template <typename ...Tail>
void foobar(const std::string& head, Tail&&... tail)
{
// do something with head
std::cout << head << '\n';
// call foobar recursively with remaining arguments
foobar(std::forward<Tail>(tail)...);
}
foobar("Hello", "World", "...");
Personally, I prefer using std::initializer_list
instead of variadic templates. Because variadic templates are more complex and require additional experience. With std::initializer_list
, it might look like this:
void foobar(std::initializer_list<std::string> values)
{
for (auto& value : values) {
// do something with value
std::cout << value << '\n';
}
}
foobar({ "Hello", "World", "...", });
Unfortunately, the additional curly braces are required when using std::initializer_list
with regular functions. They are not required for constructors, if the new initializer syntax is used.
Edit: Rewrote the answer according to the feedback. In particular I have changed the order of the two solutions/examples.
If variable parameters are all of one type, you can change the function signature to take an array of those types instead of using the '...'.
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