Jon*_*han 91 c++ struct comparison-operators
比较以下结构的两个实例,我收到一个错误:
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;
};
Run Code Online (Sandbox Code Playgroud)
错误是:
错误C2678:二进制'==':找不到哪个运算符带有'myproj :: MyStruct1'类型的左手操作数(或者没有可接受的转换)
为什么?
Ant*_*ams 121
在C++中,struct
s没有默认生成的比较运算符.你需要自己写:
bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return /* your comparison code goes here */
}
Run Code Online (Sandbox Code Playgroud)
Ton*_*roy 84
正如其他人所说,你需要自己实现一个比较功能.
有一种建议的方法要求编译器生成明显的/幼稚的(?)实现:请参阅此处.
这似乎有点无益的C++不是已经规范这一点,但往往结构/类有一些数据成员排除从比较(如柜台,缓存的结果,容器容量,最后一次操作成功/错误代码,光标),以及作为做出无数事情的决定,包括但不限于:
int
成员可能消除不相等的对象的99%的速度非常快,而一个map<string,string>
成员可能经常具有相同的条目,是相对昂贵的比较-如果值在运行时加载,程序员可以具有的见解编译器不可能vector
,list
)时是否顺序是否重要,如果是这样,是否可以在比较之前就地对它们进行排序,而不是每次进行比较时使用额外的内存来对临时数据进行排序union
比较哪个成员operator==
自己的成员和基地(但可能有compare()
或者operator<
或有str()
或者......)所以,在你明确考虑比较对于你的特定结构应该意味着什么,而不是让它编译但在运行时没有给你一个有意义的结果之前,有一个错误是很好的.
所有这一切,如果C++让你说bool operator==() const = default;
当你决定一个"天真的"逐个成员的==
测试是好的,那就好了.同样的!=
.鉴于多个成员/基地,"默认" <
,<=
,>
,以及>=
实现看起来虽然无望-级联的声明的可能,但不太可能是什么想的秩序的基础上,给出了相互矛盾迫切需要对成员排序(基地是必然成员之前,通过分组依赖使用前的可达性,构造/破坏).为了更广泛地使用,C++需要一个新的数据成员/基础注释系统来指导选择 - 这在标准中是一件好事,但理想情况下与基于AST的用户定义代码生成相结合......我期望它有一天会发生.
这是可能的,合理的和有效的实现将是:
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return lhs.my_struct2 == rhs.my_struct2 &&
lhs.an_int == rhs.an_int;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这需要一个operator==
为MyStruct2
过.
这个实现和替代方案的含义将在下面的MyStruct1细节讨论标题下讨论.
利用std::tuple
比较运算符来比较自己的类实例很容易- 只需用于std::tie
按照所需的比较顺序创建对字段的引用元组.从这里推广我的例子:
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...
Run Code Online (Sandbox Code Playgroud)
当你"拥有"(即可以编辑公司和第三方库的一个因素)你要比较的类时,特别是C++ 14准备从return
语句中推断出函数返回类型时,通常可以更好地添加"将"成员函数绑定到您希望能够比较的类:
auto tie() const { return std::tie(my_struct1, an_int); }
Run Code Online (Sandbox Code Playgroud)
然后上面的比较简化为:
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return lhs.tie() == rhs.tie();
}
Run Code Online (Sandbox Code Playgroud)
如果你想要一套更完整的比较运算符,我建议使用boost运算符(搜索less_than_comparable
).如果由于某种原因它不合适,您可能会或可能不喜欢支持宏(在线)的想法:
#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)
Run Code Online (Sandbox Code Playgroud)
......那可以用来......
#define MY_STRUCT_FIELDS(X) X.my_struct2, X.an_int
TIED_COMPARISONS(MyStruct1, MY_STRUCT_FIELDS)
Run Code Online (Sandbox Code Playgroud)
(C++ 14构件结版本这里)
选择提供一个独立的成员与成员有关operator==()
...
独立实施
你有一个有趣的决定.由于你的课程可以从a隐式构建MyStruct2
,独立/非成员bool operator==(const MyStruct2& lhs, const MyStruct2& rhs)
函数将支持...
my_MyStruct2 == my_MyStruct1
Run Code Online (Sandbox Code Playgroud)
...首先创建一个临时MyStruct1
的my_myStruct2
,然后进行比较.这肯定会将MyStruct1::an_int
set设置为构造函数的默认参数值-1
.根据您是否an_int
在执行中包含比较operator==
,MyStruct1
可能会或可能不会比较等于a MyStruct2
本身比较等于MyStruct1
的my_struct_2
成员!此外,创建临时操作MyStruct1
可能是一个非常低效的操作,因为它涉及将现有my_struct2
成员复制到临时成员,只是在比较之后将其丢弃.(当然,您可以MyStruct1
通过创建该构造函数explicit
或删除默认值来阻止此隐式构造s进行比较an_int
.)
会员实施
如果要避免MyStruct1
从a 隐式构造a MyStruct2
,请使比较运算符成为成员函数:
struct MyStruct1
{
...
bool operator==(const MyStruct1& rhs) const
{
return tie() == rhs.tie(); // or another approach as above
}
};
Run Code Online (Sandbox Code Playgroud)
注意const
关键字 - 仅对成员实现需要 - 建议编译器比较对象不会修改它们,因此可以在const
对象上允许.
有时,获得所需比较的最简单方法是......
return lhs.to_string() == rhs.to_string();
Run Code Online (Sandbox Code Playgroud)
...这通常也非常昂贵 - 那些string
痛苦的创造只是为了被扔掉!对于具有浮点值的类型,比较可见表示意味着显示的数字数决定了在比较期间几乎相等的值被视为相等的容差.
iam*_*ind 16
您需要明确定义operator ==
的MyStruct1
.
struct MyStruct1 {
bool operator == (const MyStruct1 &rhs) const
{ /* your logic for comparision between "*this" and "rhs" */ }
};
Run Code Online (Sandbox Code Playgroud)
现在==比较对于2个这样的对象是合法的.
Joe*_*Lee 12
在C ++ 20日起,它应该是可能的全套默认比较操作(添加==
,<=
通过声明等)一类的默认三路比较操作符(“宇宙飞船”运营商),就像这样:
struct Point {
int x;
int y;
auto operator<=>(const Point&) const = default;
};
Run Code Online (Sandbox Code Playgroud)
使用兼容的 C++20 编译器,假设 MyStruct2 的定义兼容,将该行添加到 MyStruct1 和 MyStruct2 可能足以允许相等比较。
归档时间: |
|
查看次数: |
98522 次 |
最近记录: |