variadic function: passing args

Georg Wrede georg.wrede at nospam.org
Fri Jul 7 02:14:45 PDT 2006


Ivan Senji wrote:
> Georg Wrede wrote:
>>Chris Nicholson-Sauls wrote:
>>>icee wrote:
>>>
>>>>is there a way to pass the ... args from one variadic function to
>>>>another variadic function?
>>>>
>>>>consider such case:
>>>>void vf1(int a, ...) {
>>>>
>>>>vf2(...);
>>>>}
>>>>void vf2(...) {
>>>>}
>>>>
>>>>can vf2 take _arguments and _argptr from vf1?
>>>>
>>>Simply way to do it, is to write vf2 twice, once as a variadic
>>>wrapper, and once taking a vararg pair.  In other words:
>>>
>>># import std .stdarg ;
>>>#
>>># void vf2 (...) { vf2(_arguments, _argptr); }
>>>#
>>># void vf2 (TypeInfo[] _arguments, va_list _argptr) {
>>>#   /* real work */
>>># }
>>>
>>>Sad to say, this is one time when I do start to miss a preprocessor
>>>just a little.  It'd be somewhat nice to be able to do:
>>>
>>>########## module altvararg ;
>>># import std .stdarg ;
>>>#
>>># #define ALT_VARIADIC(FNAME) \
>>>#   void FNAME (...) { FNAME(_arguments, _argptr; } \
>>>#   void FNAME (TypeInfo[] _arguments, va_list _argptr)
>>>#
>>>
>>>########## module foo ;
>>># import altvararg ;
>>>#
>>># ALT_VARIADIC(vf2) {
>>>#   /* real work */
>>># }
>>>
>>>Maybe if we /did/ have a way it would be better.  Maybe something like:
>>># vf2(_arguments ... _argptr);
>>>
>>>Where the '...' in this case has become an operator meaning to pass
>>>these varargs to the callee as such.  Not sure if it'd be the best
>>>syntax, but its the simplest thing that comes to mind.
>>
>>Suppose we had a new keyword, variadic. Then the compiler could
>>internally accomplish what you propose, by just rewriting, and no
>>complicated changes are needed!
>>
>>void variadic foo(...)
>>{
>>    // real work
>>}
>>
>>Of course, here the "..." is redundant. So maybe the syntax could be
>>even more simple:
>>
>>void foo(...) {
>>    // real work
>>}
>>
>>So, in essence, the compiler constructs two functions (instead of one):
>>
>>whateverReturnType foo(...) {
>>    // real work
>>}
>>
>>gets rewritten as:
>>
>>whateverReturnType foo(...) { foo(_arguments, _argptr; }
>>whateverReturnType foo(TypeInfo[] _arguments, va_list _argptr)
>>{
>>    // real work
>>}

This would be totally safe, since if some day foo gets explicitly called 
like foo(TypeInfo[], va_list), then it is obvious that the intent is 
precisely what we'd expect anyway.

In other words: even if it in principle is bad manners to gratuituously 
create not-asked-for function signatures, in this particular case there 
is no possibility of any harm.

>>Now, another change is of course handy here, and that is, if a function
>>gets invoked like
>>
>>blah = foo(...);
>>
>>then it will be rewritten as:
>>
>>blah = foo(_arguments, _argptr);
> 
> 
> Nice idea, IMO the compiler should do this for us, but it would be even
> nicer if we could do something like:
> 
> blah = foo(...[0..5]); //Pass to foo only the first five arguments

Yes, that'd be nice.

But on deeper thought, in such a case it would be required that the 
outer function gets its parameters (or at least some of them) in a 
specific order -- how else would we know to use, say, those [0..5] and 
not some others?

In other words, in that case you'd probably have to define the outer 
function with at least some of its arguments as non-variadic, from which 
follows that the whole idea becomes obsolete.

-----

Thinking of all this variadic stuff, got me on an unrelated tangent:

One could conceptually consider a TypeInfo[] somewhat like a struct 
definition. Both define a "picture" that contains some "elements" which 
individually are variables.

Along this thought, the va-list is a reference to an instance of such a 
"struct".

This raises the question, would it be useful to have a means (a library 
function or something directly in the language) of creating a TypeInfo[] 
from a struct, and vice versa?

Would this be useful in this "variadic discussion"?
Would this be useful in some totally different area?

void myFunc(...)
{
     TypeInfo[] ti = _arguments;
     createStructType(ti) mystruct;  // or some other syntax?
     mystruct = _argptr;             // This actually works already??
     // then do something useful with them :-)
}


Thus, we have created a painting of the variadic arguments.

Or, as the reverse, we might create an argument list (later to be sent 
to a function, for example) at runtime, say from a database or from user 
interaction, or whatever.

--- At this point, I must admit, I just got this idea, and I haven't 
made any effort at all to figure out whether any of this is of any use. 
Or if it is totally obsolete? Anyhow, maybe some of the smarter guys 
around here get some ideas.

I just thought I'd blurt this out (even at the risk of making a fool of 
myself), cause it looked cute. :-)



More information about the Digitalmars-d mailing list