Reverse<T>
std::cmp::Reverse<T> is a zero-cost tuple struct wrapper (#[repr(transparent)] pub struct Reverse<T>(pub T);) that inverts the comparison order of its inner value T.
Definition and Trait Implementations
#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Hash)]
#[repr(transparent)]
pub struct Reverse<T>(pub T);
impl<T: PartialOrd> PartialOrd for Reverse<T> {
fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
other.0.partial_cmp(&self.0) // Swaps `self` and `other`!
}
}
impl<T: Ord> Ord for Reverse<T> {
fn cmp(&self, other: &Reverse<T>) -> Ordering {
other.0.cmp(&self.0) // Swaps `self` and `other`!
}
}
Because Reverse<T> is annotated with #[repr(transparent)], it has the exact same memory layout, size, and ABI as T itself (size_of::<Reverse<T>>() == size_of::<T>()), and its inner value is publicly accessible via .0 or pattern destructuring Reverse(val).
Comparison on T |
Equivalent Comparison on Reverse<T> |
|---|---|
a < b |
Reverse(a) > Reverse(b) |
a > b |
Reverse(a) < Reverse(b) |
a == b |
Reverse(a) == Reverse(b) |
Multi-Column Sorting (Mixed Ascending and Descending Keys)
Beyond turning BinaryHeap<Reverse<T>> into a min-heap or BTreeMap<Reverse<K>, V> into a descending map, Reverse<T> is the standard way to express mixed-direction sorting inside .sort_by_key() or .sort_unstable_by_key() by wrapping only the descending fields of a tuple key:
use std::cmp::Reverse;
#[derive(Debug)]
struct Player {
name: &'static str,
score: u32,
penalties: u32,
}
fn main() {
let mut leaderboard = vec![
Player { name: "carol", score: 150, penalties: 2 },
Player { name: "alice", score: 200, penalties: 5 },
Player { name: "bob", score: 200, penalties: 1 },
Player { name: "dave", score: 200, penalties: 1 },
];
// Sort by:
// 1. `score` DESCENDING (`Reverse(p.score)`)
// 2. `penalties` ASCENDING (`p.penalties`)
// 3. `name` ASCENDING (`p.name`)
leaderboard.sort_unstable_by_key(|p| (Reverse(p.score), p.penalties, p.name));
for (rank, p) in leaderboard.iter().enumerate() {
println!(
"#{}: {:<6} (score={}, penalties={})",
rank + 1,
p.name,
p.score,
p.penalties
);
}
}
#1: bob (score=200, penalties=1)
#2: dave (score=200, penalties=1)
#3: alice (score=200, penalties=5)
#4: carol (score=150, penalties=2)
Descending Keys in BTreeMap and BTreeSet
Wrapping the key of a BTreeMap<Reverse<K>, V> or BTreeSet<Reverse<T>> stores and iterates elements from largest to smallest while preserving .range() and .first_key_value() semantics in descending order:
use std::cmp::Reverse;
use std::collections::BTreeSet;
fn main() {
let mut high_scores = BTreeSet::from([Reverse(120), Reverse(450), Reverse(300)]);
high_scores.insert(Reverse(500));
// `.first()` on `BTreeSet<Reverse<i32>>` returns the highest score:
println!("Highest score: {:?}", high_scores.first().map(|r| r.0));
let ordered: Vec<i32> = high_scores.into_iter().map(|Reverse(s)| s).collect();
println!("All scores descending: {ordered:?}");
}
Highest score: Some(500)
All scores descending: [500, 450, 300, 120]