c++language-lawyerargument-dependent-lookupusing-directives

Unqualified name lookup does not look in local namespace after using declaration


namespace A
{
    int overloaded_f(float some_float);
    enum class Enum { Value };
}

namespace B
{
    int overloaded_f(A::Enum some_enum);
    int f(A::Enum some_enum){
        using A::overloaded_f;
        // using B::overloaded_f;

        // return B::overloaded_f(some_enum) + overloaded_f(0.0f);
        return overloaded_f(some_enum) + overloaded_f(0.0f);

        /* error: cannot convert 'A::Enum' to 'float'
           14 |         return overloaded_f(some_enum) + overloaded_f(0.0f);
              |                             ^~~~~~~~~
              |                             |
              |                             A::Enum
        */
    }
}

int main(){ 
    A::Enum a = A::Enum::Value;
    return B::f(a);
}

Link to Godbolt.

Uncommenting the (//) code lines would remove the error.

From basic.lookup.unqual:

§6.4.1 Unqualified name lookup [basic.lookup.unqual]

  1. In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.
  2. The declarations from the namespace nominated by a using-directive become visible in a namespace enclosing the using-directive; see [namespace.udir]. For the purpose of the unqualified name lookup rules described in [basic.lookup.unqual], the declarations from the namespace nominated by the using-directive are considered members of that enclosing namespace.

Does the code snippet fail to compile because name lookup ends as soon as a declaration is found for the name?


Solution

  • Does the code snippet fail to compile because name lookup ends as soon as a declaration is found for the name?

    You're correct. The lookup of overloaded_f in the expression overloaded_f(some_enum) has two components: