简体   繁体   中英

C++ variable number of arguments

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?

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.

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 .

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);
    }
}

You can use a fixed array that is actually faster and takes less space than variable number of arguments. Because variable number of arguments does a lot of checks and safety.

mytype arr[3];
arr[0] = a;
// etc
myfunction(arr, 3);

Perhaps if you already have your own custom pointer type, you could define your own basic linked list class (this is C++ after all), with the last "pointer to next" being NULL to indicate the end of the variable number of args.

Something like this:

class MyPointer
{
  // Whatever you have/want
};

class MyArgs
{
  static int nargs; // Static class variable for total number of args
  MyPointer* data;
  MyArgs*    next; 

  public:
  MyArgs(int nargs)
  {  
    // Some funky constructor to create required number of args...
  }  

  MyPointer* operator[](int at)
  {  
    // Nice overloaded operator for you to get at data
  }  

};

class PlanToDoStuff
{
  public:
  virtual void foobar(MyArgs)=0;
};

class ActuallyDoStuff: public PlanToDoStuff
{
  public:
  void foobar(MyArgs)
  {  
    // Do stuff with args...
  }  
};

int main()
{
    MyArgs args(3);
    ActuallyDoStuff dosomething;
    dosomething.foobar(args);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM