#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;
}
这在CC
(SunOs编译器)上失败:
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'
然而,如果我删除#include <iostream>
行,它编译并运行得很好。有人敢解释一下吗?
根据Comeau的说法,这两种方式都不合法-编译器在您不#include <iostream>
时构建它可能是实际的错误,而不是其他方式(或至少在解释上存在分歧):
"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){
^
这是有道理的,这没有构建-将operator!=
放在一个未命名的命名空间中仍然将它置于与::
不同的命名空间中,我不完全确定为什么g++在没有iostream
包含的情况下构建它-如果你看看g++的预处理器输出,它没有做任何可疑的重新排序代码或任何此类废话,当然iostream
没有为A
定义operator!=
。
我手边没有c++标准的副本,但是来自IBM的这个链接至少验证了未命名的名称空间不能很好地与全局名称空间混合的说法,解释了为什么找不到您定义的operator!=
。
您还可以在匿名命名空间歧义中找到一些有用的信息。
问题是<functional>
还从tuple
和utility
中提取了几个模板,这些模板会干扰查找。
如果你要删除这个,例如,通过在GCC中只包括<bits/stl_function.h>
,那么没有问题,尽管这当然不是一个真正的解决方案。我想,如果您需要谓词,则无法实现自己的operator!=()
或为std::not_equal_to
添加显式专门化。
但是,如果您不需要使用not_equal_to
谓词,您可以通过删除所有自定义代码并添加以下代码来完全避免这个问题:
#include <utility>
using namespace std::rel_ops;
bool test = a != a;