I am trying to understand why the following code does not compile:
namespace ns {
struct S {};
}
namespace alleq {
inline bool
operator==(const ns::S
I suspect the reason has to do with the fact that a using directive is supposed to make the symbol appear as if it is in the global namespace
::
(because that is the common ancestor of namespacesalleq
andns
).
That's sort of true, but only for unqualified lookup, not argument-dependent lookup:
7.3.4 [namespace.udir]:
- A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.
Since that only applies to unqualified name lookup, it only really helps when performing name lookup from within the enclosing namespace, when name lookup looks "outwards" into enclosing namespaces. It doesn't help find unqualified names from outside the namespace (which is what ADL does).
And the next paragraph states:
- A using-directive does not add any members to the declarative region in which it appears.
i.e. A using directive makes names visible in a scope, but does not add new declarations to the scope.
The reason for the behaviour you see is simply that the standard says ADL ignores using directives:
3.4.2 [basic.lookup.argdep]
- When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
— Any using-directives in the associated namespace are ignored.