https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65336
Bug ID: 65336 Summary: name lookup finds operator in unnamed namespace Product: gcc Version: 4.9.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: thibaut.lutz at googlemail dot com This invalid code compiles despite the fact that the operator overload for B is declared in an anonymous namespace after the template. >>>>>> struct ostream {} cout; template<typename T> struct A{ T t; }; struct B{}; namespace { template<typename T> ostream& operator<< (ostream& out, const A<T>&v) { return out << v.t; } ostream& operator<< (ostream& out, const B&) { return out; } } int main(){ A<B> a; cout << a; } <<<<<< This leads the following code to print 'wrong' instead of 'right': >>>>>> #include <iostream> struct ostream {} cout; template<typename T> struct A{ T t; }; struct B{}; struct C : public B{}; ostream& operator<< (ostream& out, const B&) { std::cout << "right"; return out; } namespace { template<typename T> ostream& operator<< (ostream& out, const A<T>&v) { return out << v.t; } ostream& operator<< (ostream& out, const C&) { std::cout << "wrong"; return out; } } int main(){ A<C> a; cout << a; } <<<<<< This problem seems to be specific to operators, the following correctly fails to compile: >>>>>> #include <iostream> template<typename T> struct A{ T b; }; struct B{}; template<typename T> void foo (const A<T>&a) { foo(a.b); } void foo (const B&) { std::cout << "hello"; } int main(){ A<B> b; foo(b); } <<<<<< This might be a duplicate of 51577.