首次使用C++可变参数函数 实现类似Java遍历可变参数功能报错
问题根源
你使用的是C语言旧式可变参数语法,不支持{exprs...}形式的参数包展开操作,同时参数声明为值类型Expr<std::string>,和目标vector存储的Expr<std::string>*指针类型不匹配,因此触发构造函数匹配失败的报错。
C++有两种主流方案实现和Java可变参数等效的遍历逻辑,都可以直接调用参数的accept()方法:
方案1:使用C++可变参数模板(和Java调用方式完全一致)
该方案不需要修改调用逻辑,编译期会自动校验参数类型,性能无额外开销。
类内声明
template<typename... Exprs> std::string parenthesize(std::string name, Exprs*... exprs);
实现代码
C++17及以上版本(可直接省略vector,用折叠表达式遍历)
template<typename... Exprs> std::string AstPrinter::parenthesize(std::string name, Exprs*... exprs) { // 可选:编译期校验所有参数都是Expr<std::string>*类型 static_assert((std::is_same_v<Exprs*, Expr<std::string>*> && ...), "所有参数必须为Expr<std::string>*类型"); std::string result = "(" + std::move(name); // 直接展开参数包逐个调用accept ((result += " " + exprs->accept(this)), ...); result += ")"; return result; }
C++11/14兼容版本(转vector遍历)
#include <vector> #include <type_traits> template<typename... Exprs> std::string AstPrinter::parenthesize(std::string name, Exprs*... exprs) { std::vector<Expr<std::string>*> exprVec = { static_cast<Expr<std::string>*>(exprs)... }; std::string result = "(" + std::move(name); for (auto* expr : exprVec) { result += " " + expr->accept(this); } result += ")"; return result; }
调用方式和Java完全一致:parenthesize("func", &expr1, &expr2, &expr3)
方案2:使用std::initializer_list(代码更简洁,无模板开销)
如果所有可变参数都是同类型的Expr<std::string>*,可以用初始化列表实现,不需要写模板代码。
类内声明
#include <initializer_list> std::string parenthesize(std::string name, std::initializer_list<Expr<std::string>*> exprs);
实现代码
std::string AstPrinter::parenthesize(std::string name, std::initializer_list<Expr<std::string>*> exprs) { std::string result = "(" + std::move(name); for (auto* expr : exprs) { result += " " + expr->accept(this); } result += ")"; return result; }
调用时仅需要把可变参数用大括号包裹:parenthesize("func", {&expr1, &expr2, &expr3})
内容的提问来源于stack exchange,提问作者diego_rod
相关产品推荐
相关产品推荐

