Search code examples
c++namespacesoverload-resolutionname-lookup

How Name Lookup is applied in Namespaces


I don't understand why the following code gives error:

namespace  A
{
    void f(double x){cout<<"A::f(double)\n";}

    void f(string s){cout<<"A::f(string)\n";}

    namespace B
    {
        using namespace A;
        void f(int x){cout<<"B::f\n";}

        void call()
        {
            f(10);  // calls B::f, expected
            f(10.5); // calls B::f, why??
            string s="Hi";
            f(s);  // error, why??
        }
    }
}

My understanding was to search a name, compiler starts from current scope and continuously search enclosing scope and then global scope until it finds correct (correct means signature match or convertible in case of method) one, or gives error if none is present. So at first I tried without using namespace A in B. Then the first two call invoked B::f as expected, but f(s) was giving error. I thought names in enclosing scope are by default visible to inner scope, but clearly I was wrong. Then I place using namespace A and thought f(10.5) will call A::f for better type matching, and the problem with f(s) will be solved, but this is not the case (my understanding was using keyword bring everything to current scope from the scope which is being used). Can someone help me to understand how name lookup is applied here, thanks in advance.

Note I know how to make it work. I wanted to know why this is so? what C++ standard says about this in easy to understand language. Why my understanding is wrong?


Solution

  • That to understand the compiler behaviour it is important to reference to the following quote from the C++ Standard

    2 A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [ Note: In this context, “contains” means “contains directly or indirectly”. —end note ]

    In your example "the nearest enclosing namespace which contains both the using-directive and the nominated namespace." is namespace A. That is functions

    void f(double x){cout<<"A::f(double)\n";}
    
    void f(string s){cout<<"A::f(string)\n";}
    

    are not members of namespace B for the purpose of the unqualified lookup.

    Accotding to other quote from the C++ Standard

    1 A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).

    these function declarations are hidden by the explicit declaration of f in namespace B. So the compiler found name f in namespace B and it stopped the further search of the name.