PartialOrd and Ord
The PartialOrd and Ord traits in std::cmp define relative ordering comparisons (<, <=, >, >=), distinguishing between partial orders where some values may be incomparable (PartialOrd) and total orders where every pair of values has a well-defined ordering (Ord).
Trait Definitions
pub enum Ordering {
Less,
Equal,
Greater,
}
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
// Default implementations: lt (<), le (<=), gt (>), ge (>=)
}
pub trait Ord: Eq + PartialOrd<Self> {
fn cmp(&self, other: &Self) -> Ordering;
// Default implementations: max, min, clamp
}
PartialOrd::partial_cmp returns Option<Ordering>, yielding None when two values cannot be ordered (such as f64::NAN compared with any number). Ord::cmp returns Ordering directly and is required by sorting algorithms (slice::sort) and ordered collections (BTreeMap, BTreeSet, BinaryHeap).
Deriving Lexicographical Ordering
Applying #[derive(PartialEq, Eq, PartialOrd, Ord)] compares struct fields in top-to-bottom declaration order (and enum variants in declaration order):
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Release {
major: u32,
minor: u32,
patch: u32,
}
fn main() {
let mut releases = vec![
Release { major: 2, minor: 0, patch: 0 },
Release { major: 1, minor: 9, patch: 4 },
Release { major: 1, minor: 12, patch: 0 },
];
releases.sort();
for r in &releases {
println!("{}.{}.{}", r.major, r.minor, r.patch);
}
}
1.9.4
1.12.0
2.0.0
Implementing Ord and PartialOrd Manually
When implementing both Ord and PartialOrd manually, delegate partial_cmp directly to Some(self.cmp(other)) so that Ord, PartialOrd, and PartialEq can never disagree:
use std::cmp::Ordering;
#[derive(Debug, Eq)]
struct Job {
id: u64,
priority: u8,
}
impl PartialEq for Job {
fn eq(&self, other: &Self) -> bool {
self.priority == other.priority
}
}
impl Ord for Job {
fn cmp(&self, other: &Self) -> Ordering {
self.priority.cmp(&other.priority)
}
}
impl PartialOrd for Job {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
fn main() {
let a = Job { id: 1, priority: 3 };
let b = Job { id: 2, priority: 9 };
println!("a < b: {}", a < b);
println!("max priority: {:?}", a.max(b).priority);
}
a < b: true
max priority: 9
Total Ordering of Floats with f64::total_cmp
Because f32 and f64 only implement PartialOrd, calling .sort() on a Vec<f64> does not compile. Use .sort_by(f64::total_cmp) to sort floating-point slices with IEEE 754 total ordering.