Custom attributes
The PartialEq
, Eq
, PartialOrd
and Eq
and traits support the following attributes:
- Container attributes
- Field attributes
The PartialEq
, PartialOrd
and Ord
traits also supports the following attributes:
- Container attributes
- Field attributes
(These attributes are not relevant for Eq
which is just a marker trait.)
Enumerations
Unfortunately, there is no way for derivative to derive PartialOrd
or Ord
on
enumerations as efficiently as the built-in derive(…)
yet.
If you want to use derivative on enumerations anyway, you can add
#[derivative(PartialOrd="feature_allow_slow_enum")]
to your enumeration. This acts as a “feature-gate”.
This attribute is also allowed for PartialEq
for historical reason. It is not
necessary anymore as of v2.1.0. It was never necessary nor allowed for Eq
.
Ignoring a field
You can use derivative to ignore a field when comparing:
#![allow(unused)] fn main() { extern crate derivative; use derivative::Derivative; #[derive(Derivative)] #[derivative(PartialEq)] struct Foo { foo: u8, #[derivative(PartialEq="ignore")] bar: u8, } assert!(Foo { foo: 0, bar: 42 } == Foo { foo: 0, bar: 7}); assert!(Foo { foo: 42, bar: 0 } != Foo { foo: 7, bar: 0}); }
Compare with
Usually fields are compared using ==
, PartialOrd::partial_cmp
or Ord::cmp
. You can use an alternative comparison
function if you like:
#![allow(unused)] fn main() { extern crate derivative; use derivative::Derivative; mod path { pub struct SomeTypeThatMightNotBePartialEq; pub mod to { pub fn my_cmp_fn(_: &super::SomeTypeThatMightNotBePartialEq, _: &super::SomeTypeThatMightNotBePartialEq) -> bool { false } } } use path::SomeTypeThatMightNotBePartialEq; #[derive(Derivative)] #[derivative(PartialEq)] struct Foo { foo: u32, #[derivative(PartialEq(compare_with="path::to::my_cmp_fn"))] bar: SomeTypeThatMightNotBePartialEq, } }
foo
will be compared with ==
and bar
will be compared with
path::to::my_cmp_fn
which must have the following prototype:
Trait | Signature |
---|---|
PartialEq | fn my_cmp_fn(&T, &T) -> bool; |
PartialOrd | fn my_cmp_fn(&T, &T) -> std::option::Option<std::cmp::Ordering>; |
Ord | fn my_cmp_fn(&T, &T) -> std::cmp::Ordering; |
Custom bound
Usually if you derive CmpTrait
, a T: CmpTrait
bound is added for each type parameter T
. You can use
override this behavior if the inferred bound is not correct for you.
Eg. comparing raw pointers does not require the type to be Eq
, so you could
use:
#![allow(unused)] fn main() { extern crate derivative; use derivative::Derivative; #[derive(Derivative)] #[derivative(PartialEq)] struct WithPtr<T: ?Sized> { #[derivative(PartialEq(bound=""))] foo: *const T } }
See Default
's documentation for more details.
Packed structures
You can use derivative to implement the comparison traits on packed structures. Unlike the standard derive
, derivative does not require the structure itself to be Copy
, but like the standard derive
, it requires each (non-ignored) field to be Copy
.
#![allow(unused)] fn main() { extern crate derivative; use derivative::Derivative; #[derive(Derivative)] #[derivative(PartialEq)] #[repr(C, packed)] struct Foo { f: u32, #[derivative(PartialEq = "ignore")] t: String, } }