You do it the exact same way that you overload an operator for a struct: implement the appropriate std::ops
trait.
However, you don't really want to overload the meaning of <
, you still wish to perform a comparison.
If you run the code you typed, the compiler tells you what to do:
error[E0369]: binary operation `<` cannot be applied to type `Numbers`
--> src/main.rs:6:13
|
6 | let a = Numbers::A < 4;
| ^^^^^^^^^^^^^^
|
= note: an implementation of `std::cmp::PartialOrd` might be missing for `Numbers`
So, implement PartialOrd
:
#[derive(Copy, Clone)]
enum Numbers {
A = 1,
}
use std::cmp::Ordering;
impl PartialEq<i32> for Numbers {
fn eq(&self, other: &i32) -> bool {
(*self as i32).eq(other)
}
}
impl PartialOrd<i32> for Numbers {
fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
(*self as i32).partial_cmp(other)
}
}
fn main() {
let a = Numbers::A < 4;
}
As Sven Marnach points out:
It may be worth pointing out that this implementation only allows comparisons with Numbers
on the left-hand side and i32
on the right-hand side. Comparisons like 4 > Numbers::A
and Numbers.A < Numbers.B
would require separate implementations. In addition, since you are dealing with integers, you would also want to implement Ord
and Eq
, so for all combinations of operands you end up with twelve trait implementations.
Of course, it depends on your exact cases:
- if you want to compare
Numbers
to Numbers
, you might be able to #[derive(PartialOrd)].
- if you want
Eq
, you can derive it.
- you can write macros to reduce some of the redundancy.
See also: