Skip to content

Instantly share code, notes, and snippets.

@berkus
Last active November 18, 2022 14:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save berkus/a9bdf6e11f45253df215e4d8b65f9d3d to your computer and use it in GitHub Desktop.
Save berkus/a9bdf6e11f45253df215e4d8b65f9d3d to your computer and use it in GitHub Desktop.
Rust macro to impl Eq, PartialEq and Ord
// From https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7febfe900dd6be489692040a93b2f7bd
macro_rules! impl_comparisons {
($ty:ty) => {
impl PartialOrd for $ty {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for $ty {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == std::cmp::Ordering::Equal
}
}
impl Eq for $ty {}
};
}
#[derive(Debug)]
struct Wow(i64);
impl Ord for Wow {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl_comparisons!(Wow);
fn main() {
let x = Wow(1);
let y = Wow(2);
assert_eq!(std::cmp::Ordering::Less, x.cmp(&y));
assert_eq!(x, x);
assert_eq!(y, y);
assert!(x < y);
assert!(y > x);
assert_ne!(x, y);
assert!(!(x == y));
}
// From https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bce96fea04b6cf0f26a049d935d56ef4
macro_rules! impl_comparisons {
($ty:ty, $($field:tt), *) => {
impl Ord for $ty {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
$(
let cmp = self.$field.cmp(&other.$field);
if cmp != std::cmp::Ordering::Equal {
return cmp;
}
)*
std::cmp::Ordering::Equal
}
}
impl PartialOrd for $ty {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for $ty {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == std::cmp::Ordering::Equal
}
}
impl Eq for $ty {}
};
}
#[derive(Debug)]
struct Wow(i64);
#[derive(Debug)]
struct Wow3(i64, i64, i64);
impl_comparisons!(Wow, 0);
impl_comparisons!(Wow3, 0, 2, 1);
fn main() {
let x = Wow(1);
let y = Wow(2);
assert_eq!(std::cmp::Ordering::Less, x.cmp(&y));
assert_eq!(x, x);
assert_eq!(y, y);
assert!(x < y);
assert!(y > x);
assert_ne!(x, y);
assert!(!(x == y));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment