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