Ill-formed function call due to ambiguous function overloading
Short answer: foo(0) is ambiguous because the literal 0 is both an int and a null pointer constant. Converting it to const char* (pointer conversion) and to short (integral conversion) are both standard conversions of the same rank, so neither overload is better and the call does not compile.
#include <iostream>
void foo(const char* str) // Function 1
{
std::cout << "F1 = " << str << std::endl;
}
void foo(short n) // Function 2
{
std::cout << "F2 = " << n << std::endl;
}
int main()
{
foo("randomString"); // Function 1 is called
foo(1); // Function 2 is called
foo(0);
// In this case 0 can be implicitly treated as a null pointer or an integer
// so with 1 implicit conversion sequence compiler can deduce either of the Function 1 or 2
// Hence it is an ill-formed function call and a compilation error.
return 0;
}
Compilation Error:
ill-formed-function-call.cpp:16:5: error: call to 'foo' is ambiguous
foo(0);
^~~
ill-formed-function-call.cpp:3:6: note: candidate function
void foo(const char* str) // Function 1
^
ill-formed-function-call.cpp:7:6: note: candidate function
void foo(short n) // Function 2
^
1 error generated.
- In the above code, both foo() overloads are viable and for a compiler to choose, one of them has to have a better conversion sequence but since 0 is of type int and also a nullptr constant, in both cases we have a single conversion and hence no function is better than the other hence ill-formed.
- If the function definition had foo(int) then the compiler can treat 0 as integer without any implicit conversion and hence no error.
- Similarly if we pass foo(0L) and we have a definition like foo(long n).
Note: a null pointer constant is an integer literal with value 0 (or
nullptr). Passingnullptrinstead of0would unambiguously call Function 1.