--- title: "Ambiguous function overloading in C++: why foo(0) is ill-formed" description: "Why calling foo(0) fails to compile when foo(const char*) and foo(short) both exist: 0 converts to either with equal rank, so the call is ambiguous." date: 2023-03-24 last_modified_at: 2026-10-02 keywords: [C++, function overloading, overload resolution, null pointer constant, implicit conversion] --- # 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. ```c++ #include 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`). Passing `nullptr` instead of `0` would unambiguously call Function 1.