Variadic template: candidate expects 1 argument, 0 provided (演绎错误)
Variadic template: candidate expects 1 argument, 0 provided (deduction error)
看看这段代码
template<class T>
void print(T var)
{
std::cout << var << " ";
}
template<class... Args>
void Variadic(Args... args)
{
print(args...);
}
int main()
{
Variadic();
}
当我编译它时说:
candidate: template void print(T)
candidate expects 1 argument, 0 provided
他是对的。其实我在Parameter Pack里面并没有提供任何参数。
但是为什么这段代码可以编译?
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<>
好的,现在让我们继续:编译器看到
(print(args), 0)...
它尝试调用 print()……哦等等……参数包 为空,print() 函数有 1 个参数。
为什么它的计算结果为 auto x = {0};
?
为什么编译器没有给我与以前完全相同的错误?
您误解了 ...
扩展运算符的工作原理。在您的示例中,当 args
是一个空包时,(print(args), 0)...
展开为空,而不是 print()
。
如果 args
作为 x
给出,它将扩展为 print(x), 0
。
如果 args
作为 x, y
给出,它将扩展为 (print(x), 0), (print(y), 0)
。
等等
基本上,它扩展了所有包含 args
的表达式并将其应用于,而不仅仅是 args
位本身。
来自标准[temp.variadic]:
- A pack expansion consists of a pattern and an ellipsis, the
instantiation of which produces zero or more instantiations of the
pattern in a list. The form of the pattern depends on the context in
which the expansion occurs.
...
- The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expression produces a list E1, E2, ..., EN ,
where N is the number of elements in the pack expansion parameters.
Each Ei is generated by instantiating the pattern and replacing each
pack expansion parameter with its ith element.
根据 C++ 标准 14.5.3/p4 可变参数模板 [temp.variadic](Emphasis Mine):
A pack expansion consists of a pattern and an ellipsis, the
instantiation of which produces zero or more instantiations of the
pattern in a list (described below). The form of the pattern depends
on the context in which the expansion occurs.
注意零个或多个。在您的情况下,有一个空包,因此模式 (print(args), 0)...
的实例化为零。因此,您不会收到编译时错误,因为 expression:
auto x = {0, (print(args), 0)...};
实际计算为:
auto x = {0};
也就是说,print
不会在编译器生成的代码中被调用。
看看这段代码
template<class T>
void print(T var)
{
std::cout << var << " ";
}
template<class... Args>
void Variadic(Args... args)
{
print(args...);
}
int main()
{
Variadic();
}
当我编译它时说:
candidate: template void print(T)
candidate expects 1 argument, 0 provided
他是对的。其实我在Parameter Pack里面并没有提供任何参数。
但是为什么这段代码可以编译?
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<>
好的,现在让我们继续:编译器看到
(print(args), 0)...
它尝试调用 print()……哦等等……参数包 为空,print() 函数有 1 个参数。
为什么它的计算结果为 auto x = {0};
?
为什么编译器没有给我与以前完全相同的错误?
您误解了 ...
扩展运算符的工作原理。在您的示例中,当 args
是一个空包时,(print(args), 0)...
展开为空,而不是 print()
。
如果 args
作为 x
给出,它将扩展为 print(x), 0
。
如果 args
作为 x, y
给出,它将扩展为 (print(x), 0), (print(y), 0)
。
等等
基本上,它扩展了所有包含 args
的表达式并将其应用于,而不仅仅是 args
位本身。
来自标准[temp.variadic]:
- A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list. The form of the pattern depends on the context in which the expansion occurs.
...
- The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expression produces a list E1, E2, ..., EN , where N is the number of elements in the pack expansion parameters. Each Ei is generated by instantiating the pattern and replacing each pack expansion parameter with its ith element.
根据 C++ 标准 14.5.3/p4 可变参数模板 [temp.variadic](Emphasis Mine):
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below). The form of the pattern depends on the context in which the expansion occurs.
注意零个或多个。在您的情况下,有一个空包,因此模式 (print(args), 0)...
的实例化为零。因此,您不会收到编译时错误,因为 expression:
auto x = {0, (print(args), 0)...};
实际计算为:
auto x = {0};
也就是说,print
不会在编译器生成的代码中被调用。