Macro konst::impl_cmp

source ·
macro_rules! impl_cmp {
    (
        $($rem:tt)*
    ) => { ... };
    (
        $($rem:tt)*
    ) => { ... };
}
Expand description

For implementing const comparison semi-manually.

§Impls

This macro implements ConstCmp for all the impld types, and outputs the methods/associated constants in each of the listed impls.

§Example

§Generic type

This demonstrates how you can implement equality and ordering comparison for a generic struct.

use konst::{const_cmp, const_eq, impl_cmp, try_equal};

use std::{
    cmp::Ordering,
    marker::PhantomData,
};

pub struct Tupled<T>(u32, T);

impl_cmp!{
    impl[T] Tupled<PhantomData<T>>
    where[ T: 'static ];

    impl[] Tupled<bool>;
    impl Tupled<Option<bool>>;
     
    pub const fn const_eq(&self, other: &Self) -> bool {
        const_eq!(self.0, other.0) &&
        const_eq!(self.1, other.1)
    }
    pub const fn const_cmp(&self, other: &Self) -> Ordering {
        try_equal!(const_cmp!(self.0, other.0));
        try_equal!(const_cmp!(self.1, other.1))
    }
}

const _: () = {
    let foo = Tupled(3, PhantomData::<u32>);
    let bar = Tupled(5, PhantomData::<u32>);
     
    assert!(matches!(const_cmp!(foo, foo), Ordering::Equal));
    assert!( const_eq!(foo, foo));

    assert!(matches!(const_cmp!(foo, bar), Ordering::Less));
    assert!(!const_eq!(foo, bar));

    assert!(matches!(const_cmp!(bar, foo), Ordering::Greater));
    assert!(!const_eq!(bar, foo));

    assert!(matches!(const_cmp!(bar, bar), Ordering::Equal));
    assert!( const_eq!(bar, bar));
};

§Enum

This demonstrates how you can implement equality and ordering comparison for an enum.

use konst::{const_cmp, const_eq, impl_cmp, try_equal};

use std::cmp::Ordering;

pub enum Enum {
    Tupled(u32, u32),
    Unit,
}

impl_cmp!{
    impl Enum;
     
    pub const fn const_eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Tupled(l0,l1), Self::Tupled(r0, r1)) => *l0 == *r0 && *l1 == *r1,
            (Self::Unit, Self::Unit) => true,
            _ => false,
        }
    }
    pub const fn const_cmp(&self, other: &Self) -> Ordering {
        match (self, other) {
            (Self::Tupled(l0,l1), Self::Tupled(r0, r1)) => {
                try_equal!(const_cmp!(*l0, *r0));
                try_equal!(const_cmp!(*l1, *r1))
            }
            (Self::Tupled{..}, Self::Unit) => Ordering::Less,
            (Self::Unit, Self::Unit) => Ordering::Equal,
            (Self::Unit, Self::Tupled{..}) => Ordering::Greater,
        }
    }
}

const _: () = {
    let foo = Enum::Tupled(3, 5);
    let bar = Enum::Unit;
     
    assert!(matches!(const_cmp!(foo, foo), Ordering::Equal));
    assert!( const_eq!(foo, foo));

    assert!(matches!(const_cmp!(foo, bar), Ordering::Less));
    assert!(!const_eq!(foo, bar));

    assert!(matches!(const_cmp!(bar, foo), Ordering::Greater));
    assert!(!const_eq!(bar, foo));

    assert!(matches!(const_cmp!(bar, bar), Ordering::Equal));
    assert!( const_eq!(bar, bar));
};