简体   繁体   English

C++ 变量数 arguments

[英]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. 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 function,所有 arguments 都将属于同一类型(自定义共享指针),我也无法访问 stl 或 boost。 Is there a c++ trick that would allow me to call a func with variable arguments?是否有一个 c++ 技巧可以让我调用具有变量 arguments 的函数?

Assuming your argument types are of class Arg , you can try this:假设您的参数类型是 class Arg ,您可以试试这个:

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它使用NVI 成语
  2. It uses pointers because they will not cause temporaries to be created, even for unused default arguments.它使用指针是因为它们不会导致创建临时对象,即使对于未使用的默认 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.定义 function 以获取指向参数数组的指针和数组大小的参数。

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 .此外,如果您不想对固定大小的数组进行硬编码,您可以使用alloca来分配堆栈上的存储空间,而不必担心访问堆或调用free

Pointers to shared pointers are PODs, could you change the prototype to use the memory location of each argument?指向共享指针的指针是 POD,您能否更改原型以使用每个参数的 memory 位置? 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.您可以使用一个固定数组,它实际上比可变数量的 arguments 更快且占用空间更少。 Because variable number of arguments does a lot of checks and safety.因为 arguments 的可变编号做了很多检查和安全性。

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.也许如果您已经有自己的自定义指针类型,您可以定义自己的基本链表 class(毕竟这是 C++),最后一个“指向下一个指针”是 Z6C3E226B4D4795D518ZAB341B0824EC29 的变量的数字。

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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