Actually it is possible in gcc, with a little known built-in feature that allows you to "construct" function calls. Reference here
See for example this question, which received the answer you're looking for, it just wasn't the most popular. Here's a repost of that example code to save you the click:
int my_printf(const char *fmt, ...) {
void *args = __builtin_apply_args();
printf("Hello there! Format string is %s\n", fmt);
void *ret = __builtin_apply((void (*)())printf, args, 1000);
__builtin_return(ret);
}
int main(void) {
my_printf("%d %f %s\n", -37, 3.1415, "spam");
return 0;
}
This feature hasn't (yet) been reimplemented in clang, though there is an interesting discussion about it you can read in the archives.
So to come back to your original question of possibility, I guess we would have to clarify what passes for "possible" in this case. The C standard has no way to reference a list of variadic arguments apart from a va_list
. Compilers like gcc can put in their own extension to deal with this (like __builtin_apply
), but they will always be non-portable and non-standard.
The next question you might be tempted to ask is "why", and I can really only speculate on the answer, but I believe it's probably because doing so would require putting additional constraints and requirements on the ABI and calling convention, something that the C and C++ specifications try to avoid wherever possible.
In general, a called function has no idea how much stuff has been pushed on the stack before its entry, and I don't know of any ABIs that require this information to be present in all cases. If foo()
is going to "forward" its arguments to another variadic function, it will need to know how many things have been passed to it, and this information simply isn't available at compile time (where the call to a "next level" function will be constructed).
Only the person writing the function actually knows how to iterate over its call stack, and the chosen syntax for this is using va_list
objects.
Of course it's not hard to see how you could create an ABI that allows passing argument counts and lengths, but it's an academic exercise if all of the world's libraries that you're actually going to call into don't conform to your ABI.