[comp.lang.c++] References in variable argument lists

dspoon@ncratl.Atlanta.NCR.COM (dspoon) (04/14/89)

Hello gurus.  I've got a bit of confusion concerning how to pass a
reference to a function (not a "reference to a function"...but rather a
"reference" to a function) that defines a variable argument list.  It seems
that when I use va_arg to pull a Foo& off the va_list, it's not
automatically dereferenced.  And if I cast the result of the va_arg to a
Foo&, it tries to call a Foo constructor...which confuses me because you
can assign a reference to a reference without having the constructor
called (methinks).  I have attached the following example...have a look
and share some wisdom with me!

I tried to post this once already, but I'm pretty sure our outbound news
was hosed.  Apologies if this is your second copy!

----------------------------example follows-------------------------
//
// file = vargref.cpp
//
// this code tests variations on passing references to objects on the
// stack in a variable argument list.  the problem occurred when I was
// trying to pass a reference to an object to a function, which then
// needed to pass that reference in a va_list to another function...thus
// this second level function needed to pull the reference off the va_list
// using va_arg.  I have found a way around it (Number 4 below) but I'd
// like to understand what's going on with the examples below that don't
// work.
//
 
#include <stream.hpp>
#include <stdio.h>
#include <stdarg.h>
 
class Foo {
      int a;            // Everything's got private parts!
   public:
      Foo() {cout << "Foo ctor called!\n";}
//      Foo(Foo&) {}    // if this is defined, Number 2 below gets in
                        // a recursive call to this ctor...
      foofunc() {cout << "Here I am...\n";}
};
 
void func1(Foo &f);
void func2(int, ...);
void func3(Foo &f);
 
void func1(Foo &f)
{
   int i = 7;
   f.foofunc();
   func2(i, f);   // pass the ref to a second level function
}
 
void func2(int i, ...)
{
   va_list args;
   va_start (args, i);   // set up the va_list to pull off the next parm
 
   // Number 1:
// Foo& ff = (va_arg(args, Foo&));        // refs are not automatically 
                                          // deref'd coming from a va_list...
   // Number 2:
// Foo& ff = (Foo&) (va_arg(args, Foo&)); // wants to call a Foo ctor, but
                                          // can't find one to call unless
                                          // I make a Foo::Foo(Foo&) ctor, 
                                          // but see note in class Foo above
                                          // about what happens...
 
   // Number 3:
// Foo& ff = (*va_arg(args, Foo&));       // dereferencing a passed reference
                                          // is cheating & gets a compiler
                                          // bug anyway (under Zortech
					 //  version 1.07...
 
   // Number 4:
   Foo& ff = (*va_arg(args, Foo*));       // if a pointer to a Foo is passed
                                          // instead of passing a ref to a
                                          // Foo, deref'ing that pointer and
                                          // assigning the result to a Foo&
                                          // works fine!
   func3(ff);                             // Need to pass the ref parm
 					  // to a second level
					  // function...

   va_end(args);  // end o' the line
}
 
void func3(Foo &f)
{
   f.foofunc();
}
 
int main()
{
   Foo f1;
   func1(f1);
   Foo *f2 = new Foo;
   func1(*f2);
}
----------------------------end of example----------------------------------

-------------------------------David Witherspoon-------------------------------
D.Witherspoon@Atlanta.NCR.COM         | "It's not the code that counts...
NCR Sys Engineering-Retail/Atlanta    |   it's the attitude!"
MY OPINIONS...ALL MINE!!!             |                         - me