jaivalis
jaivalis

Reputation: 518

c++ varargs/variadic function with two types of arguments

I am trying to implement a variadic function. I searched the web and ended up finding out that most examples handle only one type of arguments (for example calculating average of many integers). Im my case the argument type is not fixed. It can either involve char*, int or both at the same time. Here is the code i ended up with :

void insertInto(int dummy, ... ) {
   int i = dummy;
   va_list marker;
   va_start( marker, dummy );     /* Initialize variable arguments. */
   while( i != -1 ) {
      cout<<"arg "<<i<<endl;
             /* Do something with i or c here */
      i = va_arg( marker, int);
      //c = va_arg( marker, char*);
   }
   va_end( marker );              /* Reset variable arguments.      */

Now this would work okay if i only had to deal with integers but as you see i have a char* c variable in comments which i would like to use in case the argument is a char*.

So the question is, how do I handle the returned value of va_arg without knowing if it is an int or a char* ?

Upvotes: 4

Views: 3111

Answers (5)

Foo Bah
Foo Bah

Reputation: 26261

You can make the processing conditional on the dummy parameter. I have routines that take an "action" argument and treats the arguments differently based on the action

For example:

int i; char *c;
switch(dummy) {
    case 1:
        i = va_arg(marker, int);
        // do something with i
        break;
    case 2:
        c = va_arg(market, char *);
        // do something with c
        break;
}

Upvotes: 0

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145249

since you're doing c++ there's no need to use untyped C-style variadic function.

you can simply define a chainable method like

  class Inserter
  {
  public:
      Inserter& operator()( char const* s )
      {
          cout << s << endl;
          return *this;
      }

      Inserter& operator()( int i )
      {
          cout << i << endl;
          return *this;
      }
  };

then use like

Inserter()( "blah" )( 42 )( "duh" )

variant with templated insert operation commonly used for building strings.

cheers & hth.,

Upvotes: 10

Arun
Arun

Reputation: 20383

From http://en.wikipedia.org/wiki/Variadic_function#Variadic_functions_in_C.2C_Objective-C.2C_C.2B.2B.2C_and_D:

In some other cases, for example printf, the number and types of arguments are figured out from a format string. In both cases, this depends on the programmer to actually supply the correct information.

So, to handle multiple types, the insertInto() need a concept like format string.

Upvotes: 0

Philipp
Philipp

Reputation: 49802

So the question is, how do I handle the returned value of va_arg without knowing if it is an int or a char* ?

You can't. There is absolutely no way to determine the type of a variadic argument. You have to specify it somewhere else. That's why functions like printf require you to give the type of the arguments in the format string:

printf("%s %i\n", "Hello", 123);  // works
printf("%s %i\n", 123, "Hello");  // also valid (though most modern compiles will emit a warning), but will produce garbage or crash

Upvotes: 3

Ben Voigt
Ben Voigt

Reputation: 283624

You need some way of knowing. Consider how printf solves this, with a format string. It's not the only possible approach, but it's a well-known one.

Upvotes: 2

Related Questions