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

問題は、<functional>からいくつかのテンプレートを取得し、ルックアップtupleutility妨げることです。

これを削除する場合、たとえば<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 に答える
0

コモーによれば、これはどちらにしても合法ではありません - コンパイラがそうでないときにそれをビルドするという事実は#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 ++からのプリプロセッサ出力を見ると、コードを並べ替えたり、そのようなナンセンスなことをしたり、もちろんfor をiostream定義したりしません。operator!=A

私はC++標準のコピーを手元に持っていませんが、 IBMからのこのリンクoperator!=は、名前のない名前空間がグローバルなものとうまく混ざらないという主張を少なくとも検証し、定義した名前が見つからない理由を説明しています.

また、 Anonymous Namespace Ambiguityで役立つ情報を見つけることができます。

于 2011-12-13T12:55:02.697 に答える