Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ variable number of arguments

Tags:

c++

I need to define a virtual function that can take variable number of arguments, problem is c style ellipses does not work for non pod types, I have limited amount of memory (2KB) so i am trying to avoid allocating temp object just to pass to the function, all arguments will be of the same type (a custom shared pointer), I also don't have access to stl or boost. Is there a c++ trick that would allow me to call a func with variable arguments?

like image 247
Hamza Yerlikaya Avatar asked Apr 27 '11 15:04

Hamza Yerlikaya


3 Answers

Assuming your argument types are of class Arg, you can try this:

class ArgUser {
public:
    // syntactic sugar:
    void method() { // nullary
        doMethod();
    }
    void method( const Arg & a1 ) { // unary
        doMethod( &a1 );
    }
    void method( const Arg & a1, const Arg & a2 ) { // binary
        doMethod( &a1, &a2 );
    }
    // and so on, until max arity
private:
    // actual virtual function:
    virtual void doMethod( const Arg * a1=0, const Arg * a2=0 /*etc, until max arity */ ) = 0;
};

This solution has the following properties:

  1. It uses the NVI idiom
  2. It uses pointers because they will not cause temporaries to be created, even for unused default arguments.
  3. It encapsulates the ugly pointer juggling in (inline) wrapper methods.

An alternative solution (that may or may not be more efficient) is this:

class AltArgUser {
public:
    // syntactic sugar:
    void method() { // nullary
        doMethod( 0, 0 );
    }
    void method( const Arg & a1 ) { // unary
        doMethod( &&a1, 1 );
    }
    void method( const Arg & a1, const Arg & a2 ) { // binary
        const Arg * args[] = { &a1, &a2 };
        doMethod( args, 2 );
    }
    // and so on, until max arity
private:
    // actual virtual function:
    virtual void doMethod( const Arg * args[], size_t numArgs ) = 0;
};

To decide which one to use, you need to study the assembler generated for each method on your particular platform. Whatever you choose, you should definitely keep the wrapper functions.

like image 199
Marc Mutz - mmutz Avatar answered Nov 08 '22 19:11

Marc Mutz - mmutz


Define the function to take a pointer to an array of parameters and a parameter for the size of the array.

Also, if you do not want to hard code a fixed sized array you could use alloca to allocate the storage on the stack and not worry about a trip to the heap or calling free.

like image 28
Dave Rager Avatar answered Nov 08 '22 21:11

Dave Rager


Pointers to shared pointers are PODs, could you change the prototype to use the memory location of each argument? Like this (not tested):

shared_ptr arg1;
shared_ptr arg2;

ClassWithVirtualFunction c;

c.yourVirtualFunction(&arg1, &arg2, NULL);

ClassWithVirtualFunction
{
    virtual void yourVirtualFunction(shared_ptr* first, ...)
    {
        va_list marker;

        va_start( marker, first );

        shared_ptr* current=first;

        while (current != NULL)
        {
            /* do stuff with *current */
            current = va_arg( marker, shared_ptr* );
        }
        va_end(marker);
    }
}
like image 1
paquetp Avatar answered Nov 08 '22 19:11

paquetp