在比较C ++中的结构时找不到==操作符

比较以下结构的两个实例,我收到一个错误:

struct MyStruct1 { Position(const MyStruct2 &_my_struct_2, const int _an_int = -1) : my_struct_2(_my_struct_2), an_int(_an_int) {} std::string toString() const; MyStruct2 my_struct_2; int an_int; }; 

错误是:

错误C2678:二进制'==':没有find操作符,它需要一个types为'myproj :: MyStruct1'的左手操作数(或没有可接受的转换)

为什么?

在C ++中, struct没有默认生成的比较运算符。 你需要写你自己的:

 bool operator==(const MyStruct1& lhs, const MyStruct1& rhs) { return /* your comparison code goes here */ } 

正如其他人所说,你需要自己实现一个比较function。

有一种build议的方式要求编译器生成显而易见的/天真的(?)实现:见这里 。

对于C ++来说,看起来似乎有点无用,但是通常结构体/类有一些数据成员要从比较中排除 (例如计数器,caching结果,容器容量,最后一次操作成功/错误代码,游标)作为关于无数事情的决定,包括但不限于:

  • 比较一个特定的int成员可能会非常快地消除99%的不等于对象,而map<string,string>成员可能通常具有相同的条目,并且相对比较昂贵 – 如果这些值在运行时加载,程序员可能对编译器不可能有深刻的见解
  • 比较string:区分大小写,空格和分隔符的等价性,转义约定…
  • 精度比较花车/双打
  • NaN浮点值是否应该被认为是相等的
  • 比较指针或指向数据(如果是后者,如何知道指针是否是数组以及需要比较多less个对象/字节)
  • 在比较未sorting的容器(比如vectorlist )时,顺序是否重要,如果是的话,比较之前是否可以对它们进行sorting。
  • 有多less数组元素当前拥有应该比较的有效值(有没有一个大小的地方或一个哨兵?)
  • 哪一个union成员比较
  • 规范化:例如,datetypes可能允许date范围外的月份或月份,或有理性/分数的对象可能有6/8,而另一个有3/4,由于性能的原因,他们更正懒散地用一个单独的标准化步骤; 您可能需要决定是否在比较之前触发正常化
  • 当弱指针无效时该怎么办
  • 如何处理不自己实现operator==成员和基础(但可能有compare()operator<str()或getters …)
  • 在读取/比较其他线程可能要更新的数据时,必须执行哪些locking

所以,直到你明确地考虑了比较对你的特定结构意味着什么, 而不是让它编译而不是在运行时给你一个有意义的结果之前,有一个错误很好的

所有这一切,如果C ++让你说bool operator==() const = default; 当你决定一个“天真”的成员,由成员==testing是可以的 。 同样的!= 。 给定多个成员/基础,“默认” <<=>>=实现似乎绝望,尽pipe – 根据声明的顺序可能,但不太可能是想要的,因为成员sorting的冲突的必要条件必须在成员之前,通过可访问性,依赖性使用之前的构build/破坏进行分组)。 为了更加广泛的用处,C ++需要一个新的数据成员/基本注释系统来指导select – 这对标准来说是一件好事,尽pipe理想的是与基于AST的用户定义的代码生成相结合…我期望它会发生一天。

平等运算符的典型实现

一个似是而非的实现

合理有效的实施可能是:

 inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs) { return lhs.my_struct2 == rhs.my_struct2 && lhs.an_int == rhs.an_int; } 

请注意,这也需要一个operator== MyStruct2

这个实现的含义和替代方法在下面的MyStruct1的细节讨论标题下讨论

==,<,> <=的一致方法

利用std::tuple的比较运算符来比较你自己的类实例是很容易的 – 只需使用std::tie来按照所需的比较顺序创build字段引用的元组。 从这里概括我的例子:

 inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs) { return std::tie(lhs.my_struct2, lhs.an_int) == std::tie(rhs.my_struct2, rhs.an_int); } inline bool operator<(const MyStruct1& lhs, const MyStruct1& rhs) { return std::tie(lhs.my_struct2, lhs.an_int) < std::tie(rhs.my_struct2, rhs.an_int); } // ...etc... 

当你“拥有”(即可以编辑一个企业和第三方库的因素)你想要比较的类时,尤其是C ++ 14准备从return语句中推导函数返回types时,通常更好的方法是添加一个将“tie”成员函数添加到您希望能够比较的类中:

 auto tie() const { return std::tie(my_struct1, an_int); } 

那么上面的比较简化为:

 inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs) { return lhs.tie() == rhs.tie(); } 

如果你想要一套更全面的比较运算符,我build议增加运算符 (searchless_than_comparable )。 如果由于某种原因不适合,您可能会也可能不会喜欢支持macros(在线)的想法:

 #define TIED_OP(STRUCT, OP, GET_FIELDS) \ inline bool operator OP(const STRUCT& lhs, const STRUCT& rhs) \ { \ return std::tie(GET_FIELDS(lhs)) OP std::tie(GET_FIELDS(rhs)); \ } #define TIED_COMPARISONS(STRUCT, GET_FIELDS) \ TIED_OP(STRUCT, ==, GET_FIELDS) \ TIED_OP(STRUCT, !=, GET_FIELDS) \ TIED_OP(STRUCT, <, GET_FIELDS) \ TIED_OP(STRUCT, <=, GET_FIELDS) \ TIED_OP(STRUCT, >=, GET_FIELDS) \ TIED_OP(STRUCT, >, GET_FIELDS) 

…然后可以使用拉…

 #define MY_STRUCT_FIELDS(X) X.my_struct2, X.an_int TIED_COMPARISONS(MyStruct1, MY_STRUCT_FIELDS) 

(这里是C ++ 14成员绑定版本)

讨论你的MyStruct1的细节

有select提供一个独立的会员operator==()

独立实施

你有一个有趣的决定。 因为你的类可以从MyStruct2隐式构造,所以一个独立/非成员bool operator==(const MyStruct2& lhs, const MyStruct2& rhs)函数将支持…

 my_MyStruct2 == my_MyStruct1 

…首先从my_myStruct2创build一个临时的my_myStruct2 ,然后进行比较。 这肯定MyStruct1::an_int设置为构造函数的默认参数值-1 。 根据是否在operator==的实现中包含an_int比较, MyStruct1可能会或可能不会与自身与MyStruct1my_struct_2成员相等的MyStruct1进行比较! 而且,创build一个临时的MyStruct1可能是一个非常低效的操作,因为它涉及到将现有的my_struct2成员复制到一个临时对象,只是在比较之后才抛弃它。 (当然,通过使构造函数explicit或删除an_int的默认值,可以防止MyStruct1的隐式构造进行比较。

会员实施

如果要避免从MyStruct2隐式构造MyStruct2 ,请将比较运算符MyStruct2成员函数:

 struct MyStruct1 { ... bool operator==(const MyStruct1& rhs) const { return tie() == rhs.tie(); // or another approach as above } }; 

注意const关键字 – 仅仅用于成员实现 – build议编译器比较对象不修改它们,所以可以在const对象上允许。

比较可见的表示

有时最简单的方法来获得你想要的比较types可以是…

  return lhs.to_string() == rhs.to_string(); 

…这通常也是非常昂贵的 – 这些string的痛苦创造只是被扔掉! 对于具有浮点值的types,比较可见表示意味着显示数字的数量决定了在比较过程中几乎相等的值被视为相等的容差。

您需要明确定义operator ==MyStruct1

 struct MyStruct1 { bool operator == (const MyStruct1 &rhs) const { /* your logic for comparision between "*this" and "rhs" */ } }; 

现在==比较是合法的2个这样的对象。

比较不适用于C或C ++中的结构。 相反,通过字段。

默认情况下,结构体没有==运算符。 你将不得不编写你自己的实现:

 bool MyStruct1::operator==(const MyStruct1 &other) const { ... // Compare the values, and return a bool result. } 

开箱即用,==运算符只适用于基元。 为了让你的代码正常工作,你需要为你的结构重载==运算符。

因为你没有为你的结构写一个比较运算符。 编译器不会为你生成,所以如果你想比较,你必须自己写。