2
#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.

并继续g++

/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>它编译和运行的行就好了。有人敢解释吗?

4

2 回答 2

0

根据 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!=其置于不同的命名空间中'没有做任何重新排序代码或任何此类废话的事情,当然也没有定义for .::iostreamiostreamoperator!=A

我手头没有 C++ 标准的副本,但来自 IBM 的这个链接至少验证了未命名命名空间与全局命名空间不能很好地混合的说法,解释了为什么找不到operator!=你定义的命名空间。

您还可以在Anonymous Namespace Ambiguity中找到一些有用的信息。

于 2011-12-13T12:55:02.697 回答
0

问题是它<functional>还会从 from 中提取几个模板,tuple并且utility会干扰查找。

如果您要删除它,例如只包括<bits/stl_function.h>在 GCC 中,那么就没有问题,尽管这当然不是一个真正的解决方案。我想如果您需要谓词,您将无法解决自己的operator!=()问题或添加明确的专业化。std::not_equal_to

但是,如果您不需要使用not_equal_to谓词,则可以通过删除所有自定义代码并添加以下内容来完全规避该问题:

#include <utility>
using namespace std::rel_ops;

bool test = a != a;
于 2011-12-13T13:20:58.560 回答