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);
}
Uncommenting the (//) code lines would remove the error.
From basic.lookup.unqual:
§6.4.1 Unqualified name lookup [basic.lookup.unqual]
- 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.- 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:
- The unqualified component: this stops searching outward as soon as it finds a declaration, which in this case means it stops at
using A::overloaded_f. - The argument-dependent component: this only looks inside the namespace associated with its argument type. In this case, the associated namespace is
A(the namespace in which the enum type is declared). It does not find anything that is inside namespaceB.