比较操作符的兼容性问题
在引入了新的比较规则之后,c++ 20引入了一些问题,这些问题在从旧的c++版本切换时可能会出现。 这里是最典型问题的本质
# include <iostream> class MyType {
private: int
value;
public:
MyType(int
i)
// implicit
constructor
from int::value
{i}
{
}
bool
operator == (const MyType & rhs)
const
{
return value == rhs.value;
}};
bool
operator == (int i, const MyType & t)
{
return t == i;
// OK
with C + +17 }
int main()}
MyType x=42; if (0 == x){
// C++17:true
std::cout << "'0 == MyType{42}' workks\n";}
}
我们有一个简单的类,它存储一个整型值,并有一个隐式构造函数来初始化对象(隐式构造函数是必要的,以支持使用=进行初始化)
class MyType {...
public:
MyType(int
i);
// implicit
constructor
from int:};
MyType
x = 42;
// OK
该类还声明了一个能够比较对象的成员
class MyType {
bool operator==(const MyType& rhs) const; };
但是,这只会为第二个操作数启用隐式类型转换。因此,类或其他一些代码可能会引入一个全局操作符来交换顺序或参数
bool operator==(int i, const MyType& t){ return t ==i;
//OK with C++17 }
通常,类应该更好地将操作符==()定义为隐藏的friend(在类结构中使用friend声明它们,以便两个操作符都成为参数并支持隐式类型转换)。然而,这是一种有效的方法,具有相同的效果。
bool operator==(int i, const MyType& t){ return t ==i;
//finds operator==(i,t) in addition to t.operator(MyType{i}) }
不幸的是,重写的语句是一个更好的匹配,因为它不需要隐式类型转换。在这里我们还没有支持向后兼容性的解决方案;然而,如果构造函数不是显式的,编译器已经开始对这样的代码发出警告。
补充说明
对隐式定义的比较运算符的请求最初是由Oleg Smolsky在 http://wg21.1ink/n3950 提出的。这个问题随后由Bjarne Stroustrup在 wg21.link/n4175 年再次提出。然而,Jens Maurer在 http://wg21.1ink/p0221r2,was 年制定的最终提议的措辞最终被否决,因为它是一个选择退出的功能(因此,现有类型将自动具有比较运算符,除非他们声明他们不希望这样做)。当时正在考虑各种提案,赫伯·萨特(Herb Sutter)在 http://wg21.1ink/p0515r0 中汇集了这些提案。最终被接受的措辞是由Herb Sutter,Jens Maurer和Walter E.Brown在 http://wg21.1ink/p0515r3 和 http://wg21.1ink/p0768r1 中制定的。然而,Barry Revzin 在 http://wg21.1ink/p1185r2 年和 wg21.link/p1630r1 中提出了重大修改。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情”