Consider this code sample
template <typename T> struct S { T t; };
template <class T> void foo(const S<T> &v)
{
bar(v.t);
}
namespace N
{
struct A {};
}
void bar(const N::A &a) {}
int main()
{
S<N::A> a;
foo(a);
}
The code fails to compile in GCC and Clang, since neither regular lookup nor ADL can resolve the call to bar
from foo
. This is perfectly expected, since the list of associated namespaces for bar
call is just N
. Global namespace is not included, global bar
is not found. All as it should be.
However, if I change it to
template <typename T> struct S { T t; };
template <class T> void foo(const S<T> &v)
{
+v.t;
}
namespace N
{
struct A {};
}
void operator +(const N::A& a) {}
int main()
{
S<N::A> a;
foo(a);
}
It suddenly begins to compile successfully in GCC. (Meanwhile, Clang rejects both versions of the code).
It appears that in the second (operator-based) version of the code GCC considers global namespace as an associated namespace for ADL as well.
If in the latter version of the code I change the call to
template <class T> void foo(const S<T> &v)
{
operator +(v.t);
}
It will again fail to compile in GCC. So, it appears some sort of special treatment is given to operators-in-expressions notation specifically, but not to function-call notation.
It this behavior standard? I don't seem to find it in the text of the document (searching for "associated namespace"), although I do vaguely remember reading something about this peculiarity of GCC.