【问题标题】:First Time Using Variadic Functions第一次使用可变参数函数
【发布时间】:2021-12-01 12:20:17
【问题描述】:

我正在尝试使一些 Java 代码适应 C++,它们在方法中使用可变参数。在他们的代码中,他们能够将参数作为for 循环中的列表进行迭代。有没有办法在 C++ 中有类似的行为?

我在理解这个概念时遇到了一些麻烦,我觉得我可能对 C++ 中的实现方式有一个基本的误解。我在网上看到了一些类似的代码,似乎将参数列表转换为向量,我尝试在下面实现(注意我需要一个指针向量,以便我可以调用accept()方法的子对象实现)。

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

代码在第 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> *>>'

我真的不需要它在向量中。我只是想知道如何访问参数列表的成员,以便可以调用他们的 accept() 方法版本。

【问题讨论】:

  • 要匹配类型,应该是{ &amp;exprs... }

标签: c++ templates inheritance variadic-templates variadic-functions


【解决方案1】:

有 3 种不同的方式来接受可变数量的参数。

首先,C 风格的可变参数。你可能不想要这个。

第二,C++ 可变参数模板。如果一切都是相同的类型,那可能就大材小用了。

最后,如果数据是 const,则类似于 std::initializer_list。否则,只需 std::vector

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

在呼叫站点,请执行printer.parenthesize("foo", {Expr0, Expr1, Expr2});。注意额外的{}

这是解决问题的最简单方法。

【讨论】:

  • 谢谢!这非常有用。 {expr1, expr2, expr3} 语法是否也适用于数组?
  • @diego 是的,但是 C++ 数组是固定大小的。 Vector就是C++所说的变长数组。
  • 可变参数模板可以正常工作,而且不会过度杀伤力。尤其是与折叠表达式结合使用时。
  • @RemyLebeau C++ 初学者按值取值的相同对象列表?我会说这是矫枉过正。
  • @Yakk-AdamNevraumont 可变参数模板参数不必按值传递,它们可以是 passed by reference/pointer
【解决方案2】:

在 C++17 及更高版本中,如果您使用 fold expression,则可以避免将可变参数复制到 vector,例如:

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

Online Demo

【讨论】:

    猜你喜欢
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多