比较操作符的兼容性问题

358 阅读2分钟

比较操作符的兼容性问题

在引入了新的比较规则之后,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/p0515r3http://wg21.1ink/p0768r1 中制定的。然而,Barry Revzin 在 http://wg21.1ink/p1185r2 年和 wg21.link/p1630r1 中提出了重大修改。


开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情