#include <functional>
#include <iostream>
struct A {
friend bool operator==( const A & a, const A & b ){
return true;
}
};
namespace {
bool operator!=( const A &a, const A & b){
return !(a==b);
}
}
int main(int argc, char **argv) {
std::not_equal_to<A> neq;
A a;
bool test = neq(a, a);
return test ? 0 : 1;
}
This fails on CC
(SunOs Compiler) with:
Error: The operation "const A != const A" is illegal.
"tempcc.cpp", line 16: Where: While instantiating "std::not_equal_to<A>::operator()(const A&, const A&) const".
"tempcc.cpp", line 16: Where: Instantiated from non-template code.
And on g++
with:
/usr/local/include/c++/3.3.2/bits/stl_function.h: In member function `bool std::not_equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A]':
tempcc.cpp:16: instantiated from here
/usr/local/include/c++/3.3.2/bits/stl_function.h:183: error: no match for 'operator!=' in '__x != __y'
However if I remove the line #include <iostream>
it compiles and runs just fine. Anyone dare to explain this?
According to Comeau, this isn't legal either way - the fact that the compiler builds it when you don't #include <iostream>
may be the actual bug, not the other way around (or at least a disagreement in interpretation):
"stl_function.h", line 99: error: no operator "!=" matches these operands
operand types are: const A != const A
bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; }
^
detected during instantiation of "bool
std::not_equal_to<_Tp>::operator()(const _Tp &, const _Tp
&) const [with _Tp=A]" at line 19 of "ComeauTest.c"
"ComeauTest.c", line 10: warning: function "<unnamed>::operator!=" was declared but
never referenced
bool operator!=( const A &a, const A & b){
^
It makes sense that this doesn't build - placing operator!=
in an unnamed namespace still puts it in a different namespace than ::
, and I'm not entirely sure why g++ builds it without the iostream
include - if you look at the preprocessor output from g++ it hasn't done anything hinky to reorder code or any such nonsense, and of course iostream
doesn't define operator!=
for A
.
I do not have my copy of the C++ standard handy, but this link from IBM at least validates the claim that unnamed namespaces don't mix that well with the global one, explaining why you can't find the operator!=
you've defined.
You also might find some helpful information in Anonymous Namespace Ambiguity.