3

この例が私の質問を最もよく表していると思います:

namespace N {

    class C {
    public:
        friend bool operator==(const C& c, const C& x) {
            return true;
        }
        friend bool f(const C& c, const C& x) {
            return true;
        }
    };

    class D {
    public:
        bool operator==(const D& x) {
            bool a = C{} == C{};      // this works
            return true;
        }
        bool f(const D& x) {
            bool a = f(C{}, C{});     // this does not work
            return true;
        }
    };
}

私は常にオーバーロードされた演算子を「呼び出し構文」を除いて関数と同じであると見なしてきました。上記の違いに気付きましたが、ADL または名前検索ルールに違いがあります (どちらかわかりません)。

bool operator==(const C& c, const C& x)が見つかったのに が見つからない理由を誰か説明できますかbool f(const C& c, const C& x)?

4

1 に答える 1

2

あなたD::f隠れてい C::fます。後者の名前を に変更しC::gて呼び出しを調整すると、正常に動作します (関数を見つけて正常にアクセスできることを示しています)。

コードは実際には演算子関数を直接呼び出しているわけではありませんが、これは言語によって行われます。したがって、演算子関数の名前を使用していないため、名前の隠蔽は適用されません。

operator==(C{}, C{})(の代わりに)と書くと、 ( demoC{} == C{} )と同じ動作が見られます。f(C{}, C{})

したがって、「オーバーロードされた演算子は、「呼び出し構文」を除いて関数と同じように常に見てきました」と言うとき、あなたはすでに頭に釘を打っています。


ここにあなたのためのいくつかの標準があります:

[C++11: 13.5/4]:通常、演算子関数は直接呼び出されません。代わりに、実装する演算子を評価するために呼び出されます (13.5.1 – 13.5.7)。ただし、関数呼び出し構文 (5.2.2) で関数の名前としてoperator-function-idを使用して、明示的に呼び出すことができます。[ 例:

complex z = a.operator+(b); // complex z = a+b;
void* p = operator new(sizeof(int)*n);

—終わりの例]

[C++11: 3.3.7/4]: [..] 4) メンバー関数内で宣言された名前は、スコープがメンバー関数のクラスの最後まで、またはそれを超えて拡張されている同じ名前の宣言を非表示にします。[..]

[C++11: 3/4]:名前は、識別子(2.11)、operator-function-id (13.5)、literal-operator-id (13.5.8)、conversion-function-id (12.3.2)、またはtemplate-id (14.2)の使用です。エンティティまたはラベルを示す(6.6.4、6.1)。

(ここでの [修飾された] operator-function-idは です::N::C::operator==。)

于 2014-06-11T16:53:36.930 に答える