递归调用variadic模板函数重载时的不明确调用

rub*_*ict 9 c++ overload-resolution variadic-templates

考虑一下这段代码:

template<typename FirstArg>
void foo()
{
}

template<typename FirstArg, typename... RestOfArgs>
void foo()
{
    foo<RestOfArgs...>();
}

int main()
{
    foo<int, int, int>();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

为什么第一种情况存在歧义?

为什么第二种情况没有歧义?

Zan*_*Jie 1

为什么第一种情况存在歧义?

RestOfArgs可以为空。

所以foo<int>可以实例化为:

template<int>
void foo()
{
}
Run Code Online (Sandbox Code Playgroud)

template<int,>
void foo()
{
    foo<>();
}
Run Code Online (Sandbox Code Playgroud)

两者都会编译,所以它是不明确的。

实际上foo<>()不会编译,但在下一次实例化时会失败,所以没关系。

为什么第二种情况没有歧义呢?

foo<int>(7)可以实例化为:

template<int>
void foo(int 7)
{
}
Run Code Online (Sandbox Code Playgroud)

template<int>
void foo(int 7)
{
    foo();
}
Run Code Online (Sandbox Code Playgroud)

但第二个是错误的,因为没有 foo 不带任何参数,所以唯一的候选者是第一个,所以不会有歧义