I have a struct that I want to use it as a key in BTreeMap
, so I implement PartialEq
, Eq
, PartialOrd
and Ord
. The last causes a problem as there is an unsafe clamp
trait method.
I implement it this way:
use std::cmp::Ordering;
#[derive(Debug, Eq, Copy, Clone)]
struct Baz(usize);
impl PartialEq for Baz {
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
fn ne(&self, other: &Self) -> bool {
self.0.ne(&other.0)
}
}
impl PartialOrd for Baz {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
fn lt(&self, other: &Self) -> bool {
self.0.lt(&other.0)
}
fn le(&self, other: &Self) -> bool {
self.0.le(&other.0)
}
fn gt(&self, other: &Self) -> bool {
self.0.gt(&other.0)
}
fn ge(&self, other: &Self) -> bool {
self.0.ge(&other.0)
}
}
impl Ord for Baz {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
fn max(self, other: Self) -> Self
where
Self: Sized,
{
Self(self.0.max(other.0))
}
fn min(self, other: Self) -> Self
where
Self: Sized,
{
Self(self.0.min(other.0))
}
fn clamp(self, min: Self, max: Self) -> Self
where
Self: Sized,
{
Self(self.0.clamp(min.0, max.0))
}
}
fn main() {
Baz(1);
}
As far as I know, clamp for integers is safe and should work just fine, but Rust gives me the error
error[E0658]: use of unstable library feature 'clamp'
--> src/main.rs:57:5
|
57 | / fn clamp(self, min: Self, max: Self) -> Self
58 | | where
59 | | Self: Sized,
60 | | {
61 | | Self(self.0.clamp(min.0, max.0))
62 | | }
| |_____^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44095
error[E0658]: use of unstable library feature 'clamp'
--> src/main.rs:61:21
|
61 | Self(self.0.clamp(min.0, max.0))
| ^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/44095
How can I solve this? I'm using Rust 1.41.
As far as I know, clamp for integers is safe and should work just fine, but Rust gives me the error
That's because the Ord::clamp
method is unstable — the compiler isn't lying to you. However, that's a method with a default implementation, so you don't need to implement it (and shouldn't, unless you can improve on the default implementation).
Helpfully, there's a section in the documentation for Ord
titled How can I implement Ord? which describes exactly what you need to do:
Ord
requires that the type also bePartialOrd
andEq
(which requiresPartialEq
).Then you must define an implementation for
cmp()
. You may find it useful to usecmp()
on your type's fields.
Of special relevance is the fact that Ord
can be derived:
This trait can be used with
#[derive]
. Whenderive
d on structs, it will produce a lexicographic ordering based on the top-to-bottom declaration order of the struct's members. Whenderive
d on enums, variants are ordered by their top-to-bottom declaration order.
Your entire code can likely be
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
struct Baz(usize);
See also: