How I can have variable number of parameters in my function in C++.
Analog in C#:
public void Foo(params int[] a) { for (int i = 0; i < a.Length; i++) Console.WriteLine(a[i]); } public void UseFoo() { Foo(); Foo(1); Foo(1, 2); }
Analog in Java:
public void Foo(int... a) { for (int i = 0; i < a.length; i++) System.out.println(a[i]); } public void UseFoo() { Foo(); Foo(1); Foo(2); }
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.
The maximum number of arguments (and corresponding parameters) is 253 for a single function.
Syntax of VarargsA variable-length argument is specified by three periods or dots(…). This syntax tells the compiler that fun( ) can be called with zero or more arguments. As a result, here, a is implicitly declared as an array of type int[].
Parameters in C functions A Parameter is the symbolic name for "data" that goes into a function. There are two ways to pass parameters in C: Pass by Value, Pass by Reference.
These are called Variadic functions. Wikipedia lists example code for C++.
To portably implement variadic functions in the C programming language, the standard stdarg.h header file should be used. The older varargs.h header has been deprecated in favor of stdarg.h. In C++, the header file
cstdarg
should be used.To create a variadic function, an ellipsis (
...
) must be placed at the end of a parameter list. Inside the body of the function, a variable of typeva_list
must be defined. Then the macrosva_start(va_list, last fixed param)
,va_arg(va_list, cast type)
,va_end(va_list)
can be used. For example:
#include <stdarg.h> double average(int count, ...) { va_list ap; int j; double tot = 0; va_start(ap, count); //Requires the last fixed parameter (to get the address) for(j=0; j<count; j++) tot+=va_arg(ap, double); //Requires the type to cast to. Increments ap to the next argument. va_end(ap); return tot/count; }
The real C++ solution is variadic templates. You'll need a fairly recent compiler and enable C++11 support if needed.
Two ways to handle the "do the same thing with all function arguments" problem: recursively, and with an ugly (but very very Standards compliant) solution.
The recursive solution looks somewhat like this:
template<typename... ArgTypes> void print(ArgTypes... args); template<typename T, typename... ArgTypes> void print(T t, ArgTypes... args) { std::cout << t; print(args...); } template<> void print() {} // end recursion
It generates one symbol for each collection of arguments, and then one for each step into the recursion. This is suboptimal to say the least, so the awesome C++ people here at SO thought of a great trick abusing the side effect of a list initialization:
struct expand_type { template<typename... T> expand_type(T&&...) {} }; template<typename... ArgTypes> void print(ArgTypes... args) { expand_type{ 0, (std::cout << args, 0)... }; }
Code isn't generated for a million slightly different template instantiations, and as a bonus, you get preserved order of you function arguments. See the other answer for the nitty gritty details of this solution.
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