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.

Reply via email to