简体   繁体   English

递归调用可变参数模板函数重载时的不明确调用

[英]Ambiguous call when recursively calling variadic template function overload

Consider this piece of code:考虑这段代码:

template<typename FirstArg>
void foo()
{
}

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

int main()
{
    foo<int, int, int>();
    return 0;
}

It does not compile due to ambiguous call foo<RestOfArgs...>();由于不明确的调用foo<RestOfArgs...>();它无法编译when RestOfArgs has only one element ( {int} ).RestOfArgs只有一个元素( {int} )。

But this compiles without error:但这编译没有错误:

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

Why is there ambiguity in the first case?为什么第一种情况有歧义?

Why is there no ambiguity in the second case?为什么在第二种情况下没有歧义?

In Function template overloading函数模板重载

There is lot of rules to tell which template function is more specialized (according to given parameters).有很多规则可以判断哪个模板函数更专业(根据给定的参数)。

The point which makes要点

template<typename> void foo();
template<typename, typename...> void foo();

ambiguous for foo<int>() , but not foo<int>()模棱两可,但不是

template<typename T> void foo(T);
template<typename T, typename... Ts> void foo(T, Ts...);

for foo(42) is the following:对于foo(42)如下:

In case of a tie, if one function template has a trailing parameter pack and the other does not, the one with the omitted parameter is considered to be more specialized than the one with the empty parameter pack.在平局的情况下,如果一个函数模板有一个尾随参数包而另一个没有,则具有省略参数的那个被认为比具有空参数包的那个更专业。

The answer by @ZangMingJie answers the difference in behavior your are observing in your code. @ZangMingJie 的回答回答了您在代码中观察到的行为差异。

I found it easier to understand the name resolution with the following change:我发现通过以下更改更容易理解名称解析:

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

When there are two or more template parameters are used, the second function gets invoked.当使用两个或多个模板参数时,将调用第二个函数。 When there is one template parameters, the first function gets invoked.当有一个模板参数时,第一个函数被调用。

Why is there ambiguity in the first case?为什么第一种情况有歧义?

RestOfArgs can be empty. RestOfArgs可以为空。

So foo<int> can be instantiated as:所以foo<int>可以被实例化为:

template<int>
void foo()
{
}

and

template<int,>
void foo()
{
    foo<>();
}

both will compile, so it is ambiguous.两者都会编译,所以它是模棱两可的。

Actually foo<>() won't compile, but it fails in the next instantiation, so it doesn't matter.实际上foo<>()不会编译,但是在下一次实例化时它会失败,所以没关系。

Why is there no ambiguity in the second case?为什么在第二种情况下没有歧义?

foo<int>(7) can be instantiated as: foo<int>(7)可以实例化为:

template<int>
void foo(int 7)
{
}

and

template<int>
void foo(int 7)
{
    foo();
}

but the second one is an error, because there are no foo taking no argument, so the only candidate is the first one, so there won't be ambiguous但是第二个是错误的,因为没有 foo 没有参数,所以唯一的候选人是第一个,所以不会有歧义

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM