Search code examples
c++overloadingambiguous-call

literal `0` being a valid candidate for int and const string& overloads causes ambiguous call


I fixed a bug recently.

In the following code, one of the overloaded function was const and the other one was not. The issue will be fixed by making both functions const.

My question is why compiler only complained about it when the parameter was 0.

#include <iostream>
#include <string>

class CppSyntaxA
{
public:
    void f(int i = 0) const { i++; }
    void f(const std::string&){}
};

int main()
{
    CppSyntaxA a;
    a.f(1);  // OK
    //a.f(0);  //error C2666: 'CppSyntaxA::f': 2 overloads have similar conversions
    return 0;
}

Solution

  • 0 is special in C++. A null pointer has the value of 0 so C++ will allow the conversion of 0 to a pointer type. That means when you call

    a.f(0);
    

    You could be calling void f(int i = 0) const with an int with the value of 0, or you could call void f(const std::string&) with a char* initialized to null.

    Normally the int version would be better since it is an exact match but in this case the int version is const, so it requires "converting" a to a const CppSyntaxA, where the std::string version does not require such a conversion but does require a conversion to char* and then to std::string. This is considered enough of a change in both cases to be considered an equal conversion and thus ambiguous. Making both functions const or non const will fix the issue and the int overload will be chosen since it is better.