2017-09-27 74 views
10

通常當我做一個std :: find時,我會把一個謂詞作爲第三個參數,但是這次我想我會以不同的方式做它,不明白爲什麼它不起作用。爲什麼不能這個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

在您的示例中,您不能執行'* constit == foo2'或'* pToRenderJob == foo2',因爲'operator =='沒有聲明爲允許'const'左操作數變爲'* this' 。如果類有一個函數'void f();' - 你不能'constit-> 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

是的,謝謝。特別是const RenderJob,而不是函數之後的那個。我不明白這一點,我可以自己比較它們,因爲operator == overload,不是std :: find只是使用operator ==函數? – Zebrafish

+4

兩者都應該是const。當編譯器在const數據上查找運算符時,它將拒絕考慮不保證const行爲的運算符。 –

+0

我現在正在理解,但仍然在我的問題的進一步例子中,右邊是非常量,所以我認爲應該調用非常量運算符==,除非當然比較const和非const。 – Zebrafish

5

在我看來像一個常量正確性問題。嘗試這樣的事情,而不是:

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

做好自己的工作,因爲你只是路過那不是普通的臨時對象的比較,也不是他們const修飾。使用std::find時,比較函數(至少通常)會接收對集合中對象的引用(通常這會被const限定),所以它需要能夠接收一個const限定的引用。

+1

哦,我明白了,它工作。但是,我能夠自己比較它們。 std :: find中的比較函數沒有使用運算符==函數嗎? – Zebrafish

+1

@斑馬魚'find'通過const引用值來比較。 –

3

但仍然沒有意義,在上面的例子中,右手邊是foo2,這是不恆定的,它應該去非constoperator==。除非有一個通用規則const和非const不能比較。

const和非const對象在語言中沒有規定無法比較。您必須確保可以使用適當的const限定符進行比較。

*pToRenderJob == foo2; 

相當於

pToRenderJob->operator==(foo2); 

即不起作用,因爲pToRenderJob不能用來調用非const成員函數。 foo2這裏不是問題。

如果使用

foo2 == *pToRenderJob 

它相當於

foo2.operator==(*pToRenderJob) 

這也是一個問題,因爲函數參數是const對象,而你的函數需要一個非const參考。再次,foo2不是問題。

製作的功能的const成員函數和製造const參考可確保在操作者的兩側const和非const對象的所有組合可以沒有任何問題地使用的參數。

+0

這是非常有趣的,所以在* pToRenderJob == foo2時,我做了實際的函數const。非常有趣,微妙的規則。 – Zebrafish

+0

@斑馬魚。要習慣這些規則需要一段時間,但不止於此,如果對語言有更深入的理解,規則開始有意義。 –