For your specific case I'd use #[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))
}
If you need to special case your Ord
implementation, you still have to write out that code, there's nothing that can save us there! You can still derive implementations for the other traits, if it makes sense to do so.
The other part of your question is ambiguous, so I'll answer it both ways I read it:
Why can't Ord
be automatically provided by anything with PartialOrd
?
Let's look at the docs for PartialOrd
and Ord
.
PartialOrd
says: "The comparison must satisfy antisymmetry and transitivity", while Ord
says: "types that form a total order". These are math terms and I won't do as good a job as Wikipedia will at describing them.
However, we can use floating point numbers as an example. Floats have a special value called NaN
. Comparing against this value is tricky. For example, all of 1.0 < NaN
, 1.0 == NaN
and 1.0 > NaN
are false! These don't form a total order, but we can still compare one value against another. This is why PartialOrd
exists - to allow us to compare types like this. incidentally, PartialEq
exists for similar reasons.
We can't define Ord
in terms of PartialOrd
because we don't have the appropriate guarantees about the underlying types. This is Rust's type system saving us from making a mistake!
Why can't PartialOrd
be automatically provided by anything with Ord
?
The problem here is that more types are PartialOrd
than they are Ord
. If we required everything to be Ord
, then we couldn't have any floating point comparisons, because they don't have a total order, or we'd have to give up on having a total order and losing out on the safety that it provides.
However, there have been ideas to automatically do this for derive
. Proposed RFC 2385 would allow the above code to be reduced to:
#[derive(Debug, Copy, Eq, Ord)]
struct MyType(isize);
when I implement PartialOrd
(gt()
, lt()
, eq()
, ge()
, le()
...)
Note that PartialOrd
does have default implementations, you only need to implement partial_cmp
. The others are there for ease-of-use or possibly performance reasons.