Inside the method N::f(int i), the call f(m) is interpreted by the compiler as a call to N::f(int) (because you're inside the struct N and have a method with that name). The compiler looks for a function named f that takes an M as a parameter in the current scope, but only sees N::f(int) which is not compatible with f(M&).
This is a case of name hiding in C++. The member function N::f(int) hides the global f(M&) function within its scope. As a result, when you try to call f(m), the compiler doesn’t look at the global scope. It only considers N::f(int), which doesn’t match.
Use the scope resolution operator to refer to the global function explicitly:
::f(m); // This calls the global f(M&) function
If it is not resolved even after explicitly calling the global function, you are probably using an old C++ compiler, because compilers supporting C++14 to C++23 execute this without any errors.