To invoke a variadic function with unamed arguments of another variadic function
I have two variadic function as foo(format, ...)
and bar(format, ...)
. I want to implement function foo
so that it can invoke bar
with the same list of arguments it has. That is,
foo(format...)
{
...
bar(format, ...);
}
For instance, invoking foo("(ii)", 1, 2)
will invoke bar
with same arguments bar("(ii)", 1, 2)
. How should this foo
function be implemented?
PS: function 开发者_运维百科bar
is from a legacy library which I cant change its interface.
Can't be done, as long as all you have is a bunch if functions with ...
arguments.
You have to plan ahead for things like that and implement each variadic fuinction in two-staged fashion
void vfoo(format, va_list *args) {
/* Process `*args` */
}
void foo(format, ...) {
va_list args;
va_start(args, format);
vfoo(format, &args);
va_end(args);
}
Once you have each of your variadic functions implemented through a pair of va_list *
function and ...
function, you can delegate the calls using the va_list *
versions of the functions
void vfoo(format, va_list *args) {
...
vbar(format, args);
...
}
GCC can construct function calls at runtime.
foo() {
void *args = __builtin_apply_args();
void *ret = __builtin_apply(bar, args, ???);
__builtin_return(ret);
}
???
is the amount of stack space the arguments take up, which is not necessarily trivial to compute: you will need to understand what the arguments are and architecture-specific details on how they are passed.
Other GCC extensions allow further trickery with macros and inline functions.
Short answer - you cannot. Make bar take a va_list
. If you're willing to lock this down to one specific compiler, you could probably do it with inline assembly, but with standard C or C++ it's not possible.
You should, as a general rule, always implement your vararg functions in terms of va_list
and then make a wrapper ellipsis function calling the real va_list
function.
This works in C++:
#include <iostream>
template<typename Format>
void meheer(const Format& format) {
std::cout << format << std::endl;;
}
template<typename Format, typename Elt, typename ... Args>
void meheer(const Format& format, const Elt & e, const Args&... args) {
std::cout << format << e;
meheer(format, args...);
}
template<typename Format, typename ... Args>
void ohai(const Format& format, const Args&... args) {
meheer(format, args...);
}
int main(int argc, char ** argv) {
ohai(1,2,3);
return EXIT_SUCCESS;
}
Output:
12131
Of course, this is C++0x specific, but it works in my not-super-recent version of gcc. See also: http://en.wikipedia.org/wiki/C%2B%2B0x#Variadic_templates
Update Added full-length example.
精彩评论