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...>();
when RestOfArgs
has only one element ({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?
prog.cpp:25:11: error: call of overloaded ‘test (char)’ is ambiguous When there is no exact type match, the compiler looks for the closest match. The closest match for “test (‘a’);” will be “void test (int a)”, since it is not present, void test (double d) and void (float f)will cause ambiguity.
In Function overloading, sometimes a situation can occur when the compiler is unable to choose between two correctly overloaded functions. This situation is said to be ambiguous. Ambiguous statements are error-generating statements and the programs containing ambiguity will not compile. Automatic type conversions are the main cause of ambiguity.
This means that all functions that have 1 or more arguments are matched to the variadic template and all functions that with no argument are matched to the empty function. This article is contributed by MAZHAR IMAM KHAN.
Ambiguous statements are error-generating statements and the programs containing ambiguity will not compile. Automatic type conversions are the main cause of ambiguity. In C++, the type of argument that is used to call the function is converted into the type of parameters defined by the function.
The answer by @ZangMingJie answers the difference in behavior your are observing in your code.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With