Variadic模板:候选人期望1个参数,0提供(扣除错误)

Variadic template: candidate expects 1 argument, 0 provided (deduction error)

本文关键字:提供 错误 模板 候选人 期望 参数 1个 Variadic      更新时间:2023-10-16

查看此代码段

template<class T> 
void print(T var)
{
    std::cout << var << " ";
}
 
template<class... Args> 
void Variadic(Args... args)
{
    print(args...);
}
int main()
{
     Variadic();
}

当我编译时说:

候选人:模板void print(t)

候选人期望1个参数,0提供

他是对的。实际上,我没有在参数包中提供任何参数。

但是,为什么此代码编译?

template<class T> 
void print(T var)
{
    std::cout << var << " ";
}
 
template<class... Args> 
void Variadic(Args... args)
{
    auto x = {0, (print(args), 0)...};
}
int main()
{
     Variadic();
}

我要做的第一件事是将第一个0推入 initializer_list&lt;&gt;

好吧,现在让我们继续:编译器看到

(print(args), 0)...

它试图调用print()...哦,等等……参数pack 是空的,print()函数为1个参数。

为什么对auto x = {0};进行评估?

为什么编译器不给我完全相同的错误?

您误解了...扩展操作员的工作方式。在您的示例中,当args是一个空包时,(print(args), 0)...不扩展为note,而不是print()

如果给出argsx,它将扩展到print(x), 0

如果给出argsx, y,它将扩展到(print(x), 0), (print(y), 0)

等。

基本上它扩展了所有包含args的表达式,并且应用于args位本身。

来自标准[temp.variadic]:

  1. 包装扩展由图案和省略号组成 实例化产生零或更多的实例化 列表中的模式。模式的形式取决于 扩展发生。

...

  1. 包装扩展的实例化既不是尺寸...表达式也不是折叠表达产生列表e1,e2,...,...,en,, 其中n是包扩展参数中元素的数量。 每个EI都是通过实例化模式并替换每个EI生成的 包装参数及其ITH元素

根据c 标准14.5.3/p4 variadic模板[temp.variadic] 重点是矿山):

包装扩展由图案和省略号组成, 实例化产生零或更多实例化 列表中的模式(如下所述)。模式的形式取决于 在发生扩展的情况下。

注意零或更多。在您的情况下,有一个空包,因此模式(print(args), 0)...的实例为零。因此,您不会遇到编译时间错误,因为表达式:

auto x = {0, (print(args), 0)...};

实际评估:

auto x = {0};

也就是说,print在编译器生成的代码中从未调用。