http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53012

             Bug #: 53012
           Summary: unrelated friend operators in same namespace interfere
                    with operator resolution outside of namespace
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: kal...@gmail.com


This code fails to compile because of "error: no match for ‘operator<<’ in
‘std::cout << val’":

#include <iostream>

namespace one {
    class A { };
}

std::ostream& operator<<(std::ostream& os, const ::one::A& ) {
    return os << __PRETTY_FUNCTION__;
}


namespace two {
    class unrelated_a {
        friend std::ostream& operator<< ( std::ostream& out, const unrelated_a&
);
    };

    class unrelated_b {
        friend std::ostream& operator<< ( std::ostream& out, const unrelated_b&
);
    };

    void output( const one::A& val )
    {
        std::cout << val << std::endl;
    }
}

int main() {
    one::A obj ;
    two::output( obj );
    return 0;
}


Ways to make it compile as expected:
A) remove either of the two (or both) unrelated class friend operators.
B) Move two::output outside of the two namespace.
C) use clang (not trying to be overly snarky here but being unsure myself if it
should be valid code I compiled it using clang with success.)

I've tried this on 4.6.3 and 4.7 with the same results.
$ g++ -v
Using built-in specs.
COLLECT_GCC=./usr/bin/g++
COLLECT_LTO_WRAPPER=/mnt/gcc-4.7/usr/libexec/gcc/x86_64-unknown-linux-gnu/4.7.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4.7.0/configure --prefix=/mnt/gcc-4.7/usr/ :
(reconfigured) ../gcc-4.7.0/configure --prefix=/mnt/gcc-4.7/usr/
--disable-multilib --enable-languages=c++
Thread model: posix
gcc version 4.7.0 (GCC) 


command to reproduce:
./usr/bin/g++ namespace_pain.cpp

compiler output:
namespace_pain.cpp: In function ‘void two::output(const one::A&)’:
namespace_pain.cpp:28:16: error: no match for ‘operator<<’ in ‘std::cout <<
val’
namespace_pain.cpp:28:16: note: candidates are:
<list of candidates>


alternate command to reproduce:
./usr/bin/g++ namespace_pain.cpp --std=c++11

compiler output for alternate command:
namespace_pain.cpp: In function ‘void two::output(const one::A&)’:
namespace_pain.cpp:28:16: error: cannot bind ‘std::ostream {aka
std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
In file included from
/mnt/gcc-4.7/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/iostream:40:0,
                 from namespace_pain.cpp:1:
/mnt/gcc-4.7/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/ostream:600:5:
error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT
= char; _Traits = std::char_traits<char>; _Tp = one::A]’

Reply via email to