我有一个新类型,我想实现Ord
:
use std::cmp::{Ord, Ordering};
struct MyType(isize);
impl Ord for MyType {
fn cmp(&self, &other: Self) -> Ordering {
let MyType(ref lhs) = *self;
let MyType(ref rhs) = *other;
lhs.cmp(rhs)
}
}
当我尝试比较我的类型的两个变量时,我会收到错误:
error[E0277]: the trait bound `MyType: std::cmp::PartialOrd` is not satisfied
--> src/main.rs:5:6
|
5 | impl Ord for MyType {
| ^^^ can't compare `MyType` with `MyType`
|
= help: the trait `std::cmp::PartialOrd` is not implemented for `MyType`
error[E0277]: the trait bound `MyType: std::cmp::Eq` is not satisfied
--> src/main.rs:5:6
|
5 | impl Ord for MyType {
| ^^^ the trait `std::cmp::Eq` is not implemented for `MyType`
当我实施PartialEq
,Eq
和PartialOrd
(gt()
,lt()
,eq()
,ge()
,{{ 1}}等等,一切正常,但如果我提供le()
,我们可以推断cmp
和lt()
等函数!这是多余的!我不喜欢这个!
在查看the docs时,我在eq()
:
Ord
这似乎是从pub trait Ord: Eq + PartialOrd<Self>
和Eq
继承的特征。为什么特征不能使用PartialOrd
函数从继承的特征中为所需方法提供默认实现?我不知道特征的继承是如何起作用的,而且搜索没有任何用处,但我认为这是应该可行的。
在Rust中如何完成?我希望不是这样......
答案 0 :(得分:9)
对于您的具体情况,我使用#[derive]
:
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
struct MyType(isize);
fn main() {
let a = MyType(5);
let b = MyType(6);
println!("{:?}", a.cmp(&b))
}
如果您需要特殊情况Ord
实施,您仍然需要写出该代码,没有任何可以拯救我们的东西!如果有意义的话,你仍然可以推导出其他特征的实现。
你问题的另一部分含糊不清,所以我会以两种方式回答它:
为什么
Ord
可以自动提供PartialOrd
?
让我们看一下PartialOrd
和Ord
的文档。
PartialOrd
说:&#34;比较必须满足antisymmetry和transitivity&#34;,而Ord
说:&#34;类型形成一个total order&#34 ;.这些都是数学术语,我不会像维基百科所描述的那样做得好。
但是,我们可以使用浮点数作为示例。浮点数具有一个名为NaN
的特殊值。与这个值相比是很棘手的。例如,1.0 < NaN
,1.0 == NaN
和1.0 > NaN
都是假的!这些不构成总订单,但我们仍然可以将一个值与另一个值进行比较。这就是PartialOrd
存在的原因 - 允许我们比较这样的类型。顺便说一下,PartialEq
出于类似的原因存在。
我们无法用Ord
来定义PartialOrd
,因为我们对基础类型没有适当的保证。这是Rust的类型系统,可以避免我们犯错!
为什么
PartialOrd
可以自动提供Ord
?
这里的问题是PartialOrd
种类型多于Ord
。Ord
。如果我们要求所有内容都是derive
,那么我们就无法进行任何浮点比较,因为它们没有总订单,或者我们没有必须放弃总订单并失去它提供的安全性。
但是,有一些想法会自动为#[derive(Debug, Copy, Eq, Ord)]
struct MyType(isize);
执行此操作。建议的RFC 2385允许将上述代码简化为:
PartialOrd
当我实施
gt()
时lt()
,eq()
,ge()
,le()
,PartialOrd
...)
请注意,cmp
具有默认实现,您只需要实现{{1}}。其他的是易于使用或可能是性能原因。
答案 1 :(得分:6)
对于初学者,您只能实施PartialOrd::partial_cmp
,lt
,le
,gt
和ge
都有默认实施。此外,如果您实施Ord
,则可以像往常一样实施cmp
,partial_cmp
变为Some(self.cmp(other))
。
但是,如果您只想委托某个领域的平等和排序概念,那么它的推导会更好,更容易:
#[derive(PartialOrd, Ord, PartialEq, Eq)]
struct MyType(isize);