Home > other >  First Time Using Variadic Functions
First Time Using Variadic Functions

Time:10-14

I am trying to adapt some Java code to C and they use variadic parameters in a method. In their code, they are able to iterate through the parameter as a list in a for loop. Is there any way to have similar behavior in C ?

I'm having some trouble wrapping my head around the concept, and I feel like I may have a fundamental misunderstanding as to how this is implemented in C . I saw some similar code online that seemed to convert the parameter list into a vector, which I tried implementing below (note that I need a vector of pointers so that I can call child object implementations of the accept() method).

std::string AstPrinter::parenthesize(std::string name, Expr<std::string> exprs...)
{
    std::vector<Expr<std::string>*> exprVec = { exprs... };
    name = "("   name;
    for (Expr<std::string>* expr : exprVec)
    {
        name  = " ";
        name  = expr->accept(this);
    }

    name  = ")";
    return name;    
}

The code gives these errors on line 52:

no instance of constructor "std::vector<_Ty, _Alloc>::vector [with _Ty=Expr<std::string> *, _Alloc=std::allocator<Expr<std::string> *>]" matches the argument list

expected a }

cannot convert from 'initializer list' to 'std::vector<Expr<std::string> *,std::allocator<Expr<std::string> *>>'

I don't really need it to be in a vector. I am just wondering as to how I can access members of the argument list so that I can call their version of the accept() method.

CodePudding user response:

There are 3 different ways to accept a variable number of arguments.

First, C style varargs. You probably do not want this.

Second, C variadic templates. If everything is the same type, probably overkill.

Lastly, something like a std::initializer_list if the data is const. Otherwise, just a std::vector.

std::string AstPrinter::parenthesize(std::string name, std::vector<Expr<std::string>> exprs)

At the call site, do printer.parenthesize("foo", {Expr0, Expr1, Expr2});. Notice the extra {}.

This is the simplest way to solve your problem.

CodePudding user response:

In C 17 and later, you can avoid the need for copying the variadic arguments into a vector if you use a fold expression, eg:

template <typename... Args>
std::string AstPrinter::parenthesize(const std::string& name, const Args&... exprs)
{
    return "("
          name
          (
            (" "   exprs.accept(this))   ... // <-- here
        )
          ")";
}

Online Demo

  • Related