2017-09-27 128 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

@斑马鱼。要习惯这些规则需要一段时间,但不止于此,如果对语言有更深入的理解,规则开始有意义。 –

相关问题