考虑这段代码:
template<typename FirstArg>
void foo()
{
}
template<typename FirstArg, typename... RestOfArgs>
void foo()
{
foo<RestOfArgs...>();
}
int main()
{
foo<int, int, int>();
return 0;
}
当foo<RestOfArgs...>();
只有一个元素(RestOfArgs
)时,由于调用模糊{int}
而无法编译。
但是这个编译没有错误:
template<typename FirstArg>
void foo(FirstArg x)
{
}
template<typename FirstArg, typename... RestOfArgs>
void foo(FirstArg x, RestOfArgs... y)
{
foo(y...);
}
int main()
{
foo<int, int, int>(5, 6, 7);
return 0;
}
为什么第一种情况存在歧义?
为什么第二种情况没有歧义?
答案 0 :(得分:1)
为什么第一种情况存在歧义?
RestOfArgs
可以为空。
因此foo<int>
可以实例化为:
template<int>
void foo()
{
}
和
template<int,>
void foo()
{
foo<>();
}
两者都会编译,所以它很模糊。
实际上foo<>()
不会编译,但在下一个实例化中失败,所以没关系。
为什么第二种情况没有歧义?
foo<int>(7)
可以实例化为:
template<int>
void foo(int 7)
{
}
和
template<int>
void foo(int 7)
{
foo();
}
但第二个是错误,因为没有foo没有参数,所以唯一的候选者是第一个,所以不会有歧义
答案 1 :(得分:1)
The answer by @ZangMingJie回答了您在代码中观察到的行为差异。
我发现通过以下更改更容易理解名称解析:
template<typename FirstArg>
void foo()
{
printf("1\n");
}
template<typename FirstArg, typename SecondArg, typename... RestOfArgs>
void foo()
{
printf("2\n");
foo<SecondArg, RestOfArgs...>();
}
int main()
{
foo<int, int, int>();
return 0;
}
当使用两个或更多模板参数时,将调用第二个函数。当有一个模板参数时,将调用第一个函数。
答案 2 :(得分:1)
在Function template overloading
中有很多规则可以告诉哪些模板函数更专业(根据给定的参数)。
要点
template<typename> void foo();
template<typename, typename...> void foo();
对foo<int>()
不明确,但不是
template<typename T> void foo(T);
template<typename T, typename... Ts> void foo(T, Ts...);
foo(42)
的如下:
如果一个平局,如果一个函数模板有一个尾随参数包而另一个没有,那么带有省略参数的那个被认为比具有空参数包的那个更专业。