2017-09-27 3 views
10

通常、std :: findを実行すると、3番目の引数として述語を入れますが、今回は別の方法で行うと思っていました。それがうまくいかない理由を理解していない。なぜこのstd :: findはこれらのオブジェクトを比較できません

#include <iostream> 
#include <vector> 
#include <algorithm> 

struct RenderJob 
{ 
    RenderJob() {}; 
    int renderJob_ID; 
    bool operator==(RenderJob& rhs) { return rhs.renderJob_ID == this->renderJob_ID; } 
}; 

int main() 
{ 
    RenderJob foo; 
    RenderJob foo2; 
    foo == foo2; // Works 

    std::vector<RenderJob> renderJobs; 

    std::find(renderJobs.begin(), renderJobs.end(), foo); // Doesn't work 
} 

答えを

編集::まあ「==」何のオペレータが 型RenderJobの左利きのオペランドを取ります(または、許容可能な変換はありません)が見つからないバイナリ感謝。ここでは、説明のようにさらに簡単

RenderJob foo; 
    RenderJob foo2; 
    foo == foo2; // Works 

    std::vector<RenderJob> renderJobs; 

    std::vector<RenderJob>::const_iterator constit = renderJobs.begin(); 

    *constit == foo2; // Doesn't work 

を失敗した理由のいくつかの例は以下のとおりです。

const RenderJob* pToRenderJob; 

*pToRenderJob == foo2; // This fails because the pointed to 
         // object is const, and cannot call the 
         // operator== function because the actual function 
         // definition is not const. 

それは他の方法で回避した場合:

foo2 == *pToRenderJob; // This would fail because the 
         // operator==(RenderJob&) the actual argument 
         // is not const. Very subtle rules 
+0

あなたの例では、 'operator =='が 'const'左オペランドを' * this'にすることを宣言していないので、 '*構成== foo2'や' * pToRenderJob == foo2'を実行することはできません。クラスに 'void f();'という関数があれば同じことになります - あなたは 'struct-> f()'や 'pToRenderJob-> f()'を実行できませんでした。しかし、その関数を 'void f()const;'に変更すれば、両方とも問題ありません。 – aschepler

+0

ありがとう、たくさんのルールがゆっくりと設定されています。 – Zebrafish

+0

あなたのクラスの中に 'renderJob_ID'を定義する必要があります:' int renderJob_ID {} '。初期化されていないオブジェクトを残すことは時期尚早の最適化です。あなたの例では、foo.renderJob_IDとfoo.renderJob_IDは* indeterminate value *を持ち、 'std :: vector renderJobs(10)'を宣言して10個の 'renderJobs'のベクトルを作成した場合、これらの10個のオブジェクトはすべてrenderJob_ID *不定値*。したがって、演算子==引き数にconstを追加した後でも、あなたのコードは引き続き動作しません。 – Oliv

答えて

14

あなたのconst修飾子をオフに左。

bool operator==(const RenderJob& rhs) const { ... } 
+2

はい、ありがとうございます。特に、RenderJobは関数の後のものではありません。私はこれを得ることはできません、私は演算子==オーバーロードのために自分自身を比較することができます、std :: does not find operator == function? – Zebrafish

+4

両方ともconstである必要があります。コンパイラがconstデータの演算子を探しているとき、constの動作を保証しない演算子については考慮しません。 –

+0

私は今理解していますが、私のさらなる例では、右辺が非constなので、非const演算子==を呼び出す必要があります。もちろん、constと非const。 – Zebrafish

5

const-correctnessの問題のように見えます。

bool operator==(RenderJob const &rhs) const { 
    return rhs.renderJob_ID == this->renderJob_ID; 
} 

は、あなただけの一時ませんでした無地のオブジェクトを集めて、また彼らは、資格のconstたため、自分が働いて比較を行う:代わりにこのような何かを試してみてください。 std::findでは、比較関数は(少なくとも通常は)コレクション内のオブジェクトへの参照を受け取ります(通常はconst修飾されます)ので、const修飾された参照を受け取ることができる必要があります。

+1

ああ、わかった、それは働いた。しかし、私は自分でそれを比較することができました。 std :: compareのcompare関数は演算子==関数を使うだけではありませんか? – Zebrafish

+1

@Zebrafish 'find'はconst参照と比較する値をとります。 –

3

しかし、それはまだ意味がありません、上記の例では、右手側は非constoperator==に行くべきか、一定ではなくなる、foo2です。 constと非constが比較できないという一般的なルールがない限り、

言語では、constと非constオブジェクトを比較できないというルールはありません。適切なconst修飾子を使用して比較できることを確認する必要があります。

*pToRenderJob == foo2; 

pToRenderJobが非constメンバ関数を呼び出すために使用することができないので、動作しない

pToRenderJob->operator==(foo2); 

と等価です。 foo2はここで問題ではありません。

あなたは

foo2 == *pToRenderJob 

を使用している場合、それはあなたの関数が非const参照を期待しながら、関数の引数がconst対象であることからも問題である

foo2.operator==(*pToRenderJob) 

に相当します。もう一度、foo2は問題ではありません。

機能をconstメンバ関数を作り、const参照オペレータの両側constと非constオブジェクトのすべての組合せが、問題なく使用することができることを確認する引数を行います。

+0

これは非常に興味深いので、実際の関数constを作ったときに働いた* pToRenderJob == foo2にあります。非常に面白い、微妙なルール。 – Zebrafish

+0

@ゼブラフィッシュ。これらのルールに慣れるまでには時間がかかりますが、それ以上のことは、言語を深く理解すれば、ルールは理にかなっています。 –

関連する問題