c++ 操作符 < = >

243 阅读3分钟

c++ 操作符 < = >

对于所有关系运算符,没有等价的规则说明定义运算符 < 就足够了。

但是,您只需定义运算符 < = >

实际上,以下内容足以使程序员使用所有的比较器:

class Value {

private: long id; ...

public:

constexpr Value(long i) noexcept :id{i} {

}

// enable use of all equality and relutional operators:

auto operator<=> (const Value& rhs) const = default; };

通常,运算符 = = 负责相等运算符,而运算符 < = > 负责关系运算符。但是,通过声明一个操作符 < = > with = default,我们使用一个特殊的规则,即默认的成员操作符 < = > :

class Value {

auto operator<=> (const Value& rhs) const = default; };

生成一个对应的成员操作符 = = ,这样我们就可以有效地得到:


class Value {

...

auto operator<=> (const Value& rhs) const =default; 

auto operator== (const Value& rhs) const =default;

//implicitly generated };

这样做的结果是,两个运算符都使用它们的默认实现,即逐个成员比较对象。这意味着类中成员的顺序很重要。

因此,与

class Value { 

...

auto operator<=> (const Value& rhs) const = default; };

我们可以使用所有六个比较运算符。

此外,即使将运算符声明为成员函数,生成的运算符

· 如果在编译时可以比较成员,则为 conexpr

· 由于重写,如果定义了相应的隐式类型转换,则还支持第一个操作数的隐式类型转换(尽管它不作为参数传递)

· 如果没有使用比较结果可能会发出警告(这取决于编译器)

这反映了在一般情况下,运算符= =和运算符< = >关注不同但相关的事情:

运算符 = = 定义了相等性,可以由相等操作符 = = ! = 使用。

· 运算符 < = > 定义了顺序,可以由关系运算符 << => > =使用。

为了对生成的比较运算符有更多的控制权,您可以自己定义运算符 = = 和运算符 < = > ,例如:



class Value{

private: long id; ...

public:

constexpr Value(long i) noexcept : id{i} {

} ...

//for equality operators:

bool operator== (const Value& rhs) const { return id == rhs.id;

// defines equality (==and!=) }

// forrelutional operators:

auto operator<=> (const Value& rhs) const { return id <=> rhs.id;

//defines ordering(<,<=,>,and>=) }

};

这些基本运算符的工作方式是,如果一个表达式使用其中一个比较运算符,并且没有找到匹配的直接定义,那么该表达式将被重写,以便可以使用这些运算符。对应于相等运算符的重写调用,重写还可能改变关系操作数的顺序,这可能会为第一个操作数启用隐式类型转换。例如,如果:

x<=y

如果找不到与运算符 < = 匹配的定义,则可以将其重写为

(x<=>y)<=0

甚至

0(y <=>x)

通过这种重写可以看到,new 运算符 < = > 执行三向比较,得到一个可以与0进行比较的值:

· 如果 x < = > y 比较等于0,x 和 y 等于或等于。

· 如果 x < = > y 小于0,则 x 小于 y。

· 如果 x < = > y 的值比较大于0,则 x 大于 y。

运算符 < = > 的返回类型不是一个整数值。返回类型是一种表示比较类别的类型,可以是强序、弱序或纯序。这些类型支持与 0 进行比较以处理结果。


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