Search code examples
c++overload-resolutionname-lookup

Overload resolution in nested namespace with parent namespace


I thought that in a nested namespace, anything that is part of the parent (or global) namespace is considered equally for overload resolution, but this example seems to show otherwise.

This works fine:

#include <iostream>

void foo(int) { std::cout << "int\n"; }
void foo(float) { std::cout << "float\n"; }

namespace NS {
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}

The call to foo(0) matches foo(int) since it is a better match and everything works as expected. However, if I move the declaration of foo(float) into the namespace:

#include <iostream>

void foo(int) { std::cout << "int\n"; }

namespace NS {
    void foo(float) { std::cout << "float\n"; }
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}

The call to foo(0) now calls foo(float)!

I have searched through https://en.cppreference.com/w/cpp/language/overload_resolution and many other such pages to find the rule that explains this, but I seem to be missing it. Can someone please explain which of the many complex overload resolution rules causes this, or is it something else?

EDIT
I just discovered it is even weirder. Even if the foo inside the namespace doesn't match at all, it still won't use the one outside. This just completely fails to compile:

#include <iostream>

void foo(int) { std::cout << "int\n"; }

namespace NS {
    void foo(float, float) { std::cout << "float\n"; }
    void bar() {
        foo(0);
    }
}

int main() {
    NS::bar();
}

Solution

  • The point is name lookup, which happens before overload resolution.

    When the name foo is found at the namespace NS, name lookup stops, the further scopes won't be checked, the global foo won't be found at all. Then there's only one candidate in overload resolution, and int could convert to float implicitly, then NS::foo(float) gets called at last.

    (emphasis mine)

    name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.