Inferring namespace of freestanding function

Question on namespace qualification: Why isn't the namespace of the function inferred below?

namespace X {

void func(int) {}

struct Z{
   void func(){
      //func(int{}); does not compile
      X::func(int{}); // this works
   }
};

}

int main() {
   X::Z z;
   z.func();
}

Solution 1:

This specific part of C++ can be generally called "unqualified name lookup". This term describes taking a single identifier in a C++ program and then determining which actual type, or object, or function, or class, it is referencing.

For example, there can be many things called rosebud in a C++ program, so

rosebud();

This can reference a class method of this name, and this calls it. Or this could be an object with an overloaded () operator, which invokes it. There could also be something called rosebud() in a different namespace. Unqualified name lookup specifies which one of these this particular rosebud references.

struct Z{
   void func(){

Here we're in a method of class Z. Unqualified name lookup first looks for identifiers that are members of this class. Only if it's not found then does unqualified name lookup looks in the global namespace, to see if something is there.

      func(int{}); // does not compile

Well, there happens to be a method with the name func in this class, so this func's unqualified name lookup resolves to this method. This fails, because that func method takes no parameters.

Unqualified name lookup considers where exactly the unqualified identifier occurs. When it occurs in a class, unqualified name lookup searches the class's members, first.

Even though there's also a func function in the global scope, unqualified lookup finds the class method, and that's it (quoting from the cited link):

[unqualified] 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.

End of the road. The fact that there's also a func in the global namespace is immaterial. For unqualified name lookup, once "something" is found, it better work, or else.

These are just one of the rules of unqualified name lookup.

X::func(int{}); // this works

Well, yes. This explicitly references func in the X namespace. This symbol is (partially) qualified with an explicit namespace reference.