The reason is truly arcane, and has to do with the way both using
directive and overload resolution works.
First, let's look at the using
directive. When you inject namespace with it within another namespace, it works by actually injecting the namespace into
the nearest enclosing namespace which contains both the
using-directive and namespace [being used]. (https://en.cppreference.com/w/cpp/language/namespace#Using-directives).
In your case, such namespace would be global namespace, is it would be the only one encompassing the std
and My Space
. The effect of it would be that names, defined in namespace std
would behave as if they are defined in global namespace.
Let's look at overload resolution now. When the function is looked up by the name, the name is first searched in local namespace, and if not found, search continues in surrounding namespace, then one level up... - until the name(s) is(are) found, or we reach global namespace. Once at least one name is found, search stops there, and a qualified overload is chosen from the set of names using overload rules. In your case, this search immediately yields a single name - to_string
- which is than rejected, as it does not accept int
argument (it only accepts X
).
On the other hand, when you do not use MySpace
, names from std
are put in the global namespace as well, but your own to_string
exists in global namespace now. As a result, multiple to_string
versions are found in global namespace, including yours, and the proper one to_string(int)
is than selected based on the argument type.