Search code examples
c++namespacesargument-dependent-lookupname-lookup

How does a using-declaration reduce the names available for lookup without ADL?


#include <iostream>
#include <string>

class X {};

namespace N
{

std::string to_string(X)
{
    return "foo";
}

void foo()
{
    //using std::to_string; // will break the build if uncommented...
    //using N::to_string;   // ...unless this is uncommented as well
    std::cout << to_string(X()) << std::endl;
}

}

int main()
{
    N::foo();
    return 0;
}

Either I have stumbled upon one of the many C++ arcana I do not master, or I am missing something obvious here.

How can using std::to_string apparently reduce the set of names available during unqualified lookup to only those reachable via ADL? While I can guess the problem might be that to_string(X) is declared in a different namespace than X, I cannot help but notice that, without using std::to_string, N::to_string(X) is simply available to N::foo() by using the "normal", intuitive lookup rules I am accustomed to.


Solution

  • This is not specific to a using-declaration, but follows normal scoping rules. When you introduce a name into the function, that hides equally named things from outer scopes.

    You could just as well have an int to_string; local variable in foo. That would also hide N::to_string.