variadic function - how to ensure parameters passed correctly - c++

Is there any way (built-in or a code pattern) to ensure that a variadic function is passed the correct number of parameters? (This will be included as part of an API obviously, I can check my own internal code.)
I was considering requiring a UN32 Magic Number to be the last argument passed and check that for validity in the variadic function. Does anyone have any thoughts on that?

va_* macros just pop the variables from the local stack, so you have to trust the user. passing an array/size tuple could be safer, I think.

You could use the PP_NARG macro to add a count semi-automatically.
int myfunc (int count, ...);
#define MYFUNC(...) myfunc(PP_NARG(__VA_ARGS__), __VA_ARGS__)
MYFUNC(a,b,c,d);
MYFUNC(a,b,c,d,e,f,g);
gcc -E produces:
int myfunc (int count, ...);
myfunc(4, a,b,c,d);
myfunc(7, a,b,c,d,e,f,g);

There is no definitive way in C or C++ to ensure that the correct number of arguments have been passed to a variadic function. Even requiring a signature is not guaranteed to work as it may clash with the value of a valid argument. You will probably be much better off passing a vector<> as the element count retrieved is accurate.

Couldn't you use the variadic template feature of C++0x applied to a function? This would generate a vararg function that is type-safe .
See this link with it's type-safe printf implementation using a variadic templated function
http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates

It depends on what you mean by "ensure that a variadic function is passed the correct number of parameters"...
Passing a UN32 Magic Number as last argument will allow you to determine where the list of arguments ends, so their overall number. So, by counting how many arguments you have found before UN32, you know how many arguments you have and your function should know whether is it enough. Don't know if it is ok for you to determine this at run-time (it could be too late)...
Anyway, usually variadic functions have a fixed argument list portion representing the mandatory arguments (at least one); so possibly this should be the way for you to ensure that the function gets the correct number of arguments...

No. Not possible.
Variadic breaks type-safety in a way that cannot be fixed.
If you want type-safety back, then consider breaking variadic function into several typesafe
member function of a [small] class that holds the shared state between their calls.
This is always possible, even if multiple calls might look awkward compared to single variadic
call.
Shared state is probably why you wanted variadic function in the first place.
Take iostream vs printf as example.

Related

How do to pass variable number of arguments to a function in c++ with no named parameters

I need to write a function which takes a variable number of arguements, its essentially a wrapper around a snprintf like function. I understand how to do this in general as shown in Passing variable number of arguments around.
How ever it appears that, atleast in C, we are required to pass one named parameter to the function before the variable arguments start( Why is void f(...) not allowed in C? ).
However the answers to the same questions say this is easily possible in C++. I was wondering how to achieve this, especially since the method for handling vararg functions seems to be the same as C(va_start, etc). Or are they referring to variadic templates?
So basically is it possible to write a variadic function with no named arguements, as shown below, and if so, how?
void f(...){
...
}
p.s. I would like to do this with c++03 if possible.
While C++ language allows writing functions whose parameter list consist only of ..., the language provides no means for accessing the arguments in functions declared with (...) parameter list.
Basically such functions in C++ exist for their behavior in overload resolution (... parameters match any parameter type). The body of such function will not have access to the arguments. If you see no uses for such functions, just don't use them.
Such functions are often used in non-executed context in some well-known template meta-programming techniques, in which case they don't even have to be defined - a mere declaration is sufficient.

Is there a standard way of determining the number of va_args?

I'm experimenting with variable arguments in C++, using va_args. The idea is useful, and is indeed something I've used a lot in C# via the params functionality. One thing that frustrates me is the following excerpt regarding va_args, above:
Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list).
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself. I would like to perform something like the following:
void fcn(int arg1 ...)
{
va_list argList;
va_start(argList, arg1);
int numRemainingParams = //function that returns number of remaining parameters
for (int i=0; i<numRemainingParams; ++i)
{
//do stuff with params
}
va_end(argList);
}
To reiterate, the documentation above suggests that va_arg doesn't determine whether the retrieved arg is the last in the list. But I feel this information must be accessible in some manner.
Is there a standard way of achieving this?
I find it hard to believe that there is no way to programmatically determine the number of variable arguments passed to the function from within that function itself.
Nonetheless, it is true. C/C++ do not put markers on the end of the argument list, so the called function really does not know how many arguments it is receiving. If you need to mark the end of the arguments, you must do so yourself by putting some kind of marker at the end of the list.
The called function also has no idea of the types or sizes of the arguments provided. That's why printf and friends force you to specify the precise datatype of the value to interpolate into the format string, and also why you can crash a program by calling printf with a bad format string.
Note that parameter passing is specified by the ABI for a particular platform, not by the C++/C standards. However, the ABI must allow the C++/C standards to be implementable. For example, an ABI might want to pass parameters in registers for efficiency, but it might not be possible to implement va_args easily in that case. So it's possible that arguments are also shadowed on the stack. In almost no case is the stack marked to show the end of the argument list, though, since the C++/C standards don't require this information to be made available, and it would therefore be unnecessary overhead.
The way variable arguments work in C and C++ is relatively simple: the arguments are just pushed on the stack and it is the callee's responsibility to somewhat figure out what arguments there are. There is nothing in the standard which provides a way to determine the number of arguments. As a result, the number of arguments are determined by some context information, e.g., the number of elements referenced in a format string.
Individual compilers may know how many elements there are but there is no standard interface to obtain this value.
What you could do instead, however, is to use variadic templates: you can determine very detailed information on the arguments being passed to the function. The interface looks different and it may be necessary to channel the arguments into some sort of data structure but on the upside it would also work with types you cannot pass using variable arguments.
No, there isn't. That's why variable arguments are not safe. They're a part of C, which lacks the expressiveness to achieve type safety for "convenient" variadic functions. You have to live with the fact that C contains constructions whose very correctness depends on values and not just on types. That's why it is an "unsafe language".
Don't use variable arguments in C++. It is a much stronger language that allows you to write equally convenient code that is safe.
No, there's no such way. If you have such a need, it's probably best to pack those function parameters in a std::vector or a similar collection which can be iterated.
The variable argument list is a very old concept inherited from the C history of C++. It dates back to the time where C programmers usually had the generated assembler code in mind.
At that time the compiler did not check at all if the data you passed to a function when calling it matched the data types the function expected to receive. It was the programmer's responsibility to do that right. If, for example, the caller called the function with a char and the function expected an int the program crashed, although the compiler didn't complain.
Today's type checking prevents these errors, but with a variable argument list you go back to those old concepts including all risks. So, don't use it if you can avoid it somehow.
The fact that this concept is several decades old is probably the reason that it feels wrong compared to modern concepts of safe code.

Usage of variadic functions

What are the benefits of using
variadic functions
void fun(int i, ...);
instead of passing a pointer to an array?
void fun(int i*);
When are variadic functions preferred?
You have to explicitly create the array first. In addition, it would be problematic if you wanted to specify parameters of different types.
Variadic functions do not require creating any array and they can deal with different types.
As an example, I could not bare to use the printf-functions if I always had to create some array first.
On the other hand, in most cases it's just a form of syntactic sugar, I suppose.
Pointer to array assumes predefined type of the parameter (or struct, if its several different types).
Variadic functions are used when you don't know ahead of time what would the type of the parameter be, and you use a hint of the predefined parameters to get that knowledge (like the format string for printf).
Also, you don't want to pass an array in a variadic function, as you would also want to pass in its size. e.g:
myfunction(int *pArray, int NumElements)
The main point, though, is that variadic functions allow many different types to be passed.
I would suggest you to simply not use variadic functions. However they can be useful. For example in template metaprogramming techniques to implement compile-time querys.
As the compiler can't verify that a given call to a variadic
function passes an appropriate number of arguments or that those
arguments have appropriate types. Consequently, a runtime call to a
variadic function that passes inappropriate arguments yields
undefined behavior.
In pure C environments variadic functions have no alternative but in
c++ you are able to find object oriented alternatives (also one
issue).
Variadic functions are not trivial to implement. Failing to initialize ap, calling va_arg() one time to many or omitting the va_end(ap) call can crash your program.
Example of being close to undefined behavior:
It was my job to crate a object-oriented wrapper around the sqlite C api.
Here I am: I created a fancy interface for executing sqlite querys it was something like that:
void Query(const std::string& Query, void* Arguments, ...);
This is on one side awesome and fancy but: You immediately encounter undefined behavior if your parameter types are wrong. For example:
db->Query("select * from northwind where id = ?", "Peter"); // espects int as type
Will result in undefined behavior.

variable argument list in windows va_list

I wanted to have function which will accept as
foo(...)
{
//......
}
usage of this would be
foo(1,2,3);
foo(1)
foo(1,2,3,4,5,5,6);
va_list can be used but again for that I have to pass foo(int count, ...), as this at run time i dont know how many argument i have.
any pointer would be appreciated
Thanks
You need to provide the function some way to determine how many arguments it's called with: either a count (or something from which a count can be determined, such as printf's format argument), or a terminator (none of the arguments will be allowed to be equal to the terminator, except the last one that must be exactly equal to the terminator). The function can't just know "by magic" when its variadic list of arguments is finished.
Variadic functions in C and C++ are not type-safe. So you cannot do what you want without some mechanism for marking the end of the argument list. You also need to have at least one "fixed" argument so that the macros can know where the start of your argument list is in memory.
This is the reason why passing the "count" as the first argument is useful: it solves both of those problems in one hit.
Note that it works out OK for things like printf because the format string is a fixed parameter, and the "count" of variadic argument is implicit in the format string.
It's not possible to build an argument list at runtime in C, so it is absolutely certain that you know how many arguments each call to f() is using at compile-time.

Wrap a variable parameter function in C++

I would like to wrap the xmlrpc "call" function (which takes a variable number of parameters) with another function (also taking a variable number of parameters). I would like to simply forward the variable number of parameters I get passed in to my wrapper function to the xmlrpc "call" function.
I know how to use va_start and va_arg, but I really don't care about the values that are passed in, I simply want to forward them along to the wrapped function.
Is this possible?
the spec for the function i would like to wrap is
call(const char* url, const char* function, const char* paramSpec, void* result, ...);
my wrapper takes care of the first three parameters and the by reference result, it just needs to forward its extra parameters over to the call function
Unfortunately, there is no way to provide perfect forwarding of a function that takes a variable number of arguments via the ... syntax. This is why it is a best practice to implement all public variable argument list functions in terms of functions taking a va_list and provide both interfaces to any client code. This is why there is printf and vprintf, sprintf and vsprintf, etc. in the standard library.
If there isn't a vcall or similar taking a va_list then there is no easy way to do what you want. The only possibility is to interpret the other parameters to work out what must be in the variable argument list passed to your function based on the supplied fixed parameters, to pull all the arguments from the variable argument list into separate variables and make one of a number of possibly explicit calls to call based on the number and type of arguments extracted. It is not possible to do this with complete generality.
Yes, if you have control over the wrapped function, change from "..." to va_list. Look at vprintf as an example.
Not sure if you can wrap (...) with another (...)
This may be possible with evil hacks on some platforms. On x86, arguments are pushed onto the stack from right to left, so if you were to remove the return address from the stack, push your additional arguments, then replace it, you could (in theory) do what you want. The hard part is when you then want to do something with the return value from within the wrapper...