#[solved] Max of const generic parameter with bound

3 messages · Page 1 of 1 (latest)

bold thorn
#

I am writing a library for fun, which will include a FixedPoint struct for fixed-point arithmetic.

struct FixedPoint<const D: u8, T>

The D parameter stands for how many bits are after the point. However I am restricting the values of it because it must be less than or equal to the number of bits of T:

struct Guard<const G: bool>;

trait Protect {}

impl Protect for Guard<true> {}

#[derive(Eq, Ord, Clone, Copy)]
struct FixedPoint<const D: u8, T>
where
    T: Shr<u8, Output = T> + Copy,
    Guard<{ D as usize <= std::mem::size_of::<T>() * 8 }>: Protect,

So far, this works but I ran into trouble implementing Add:

impl<const D: u8, const E: u8, T> Add<FixedPoint<E, T>> for FixedPoint<D, T>
where
    T: Shr<u8, Output = T> + Add<T, Output = T> + Copy,
    Guard<{ D as usize <= std::mem::size_of::<T>() * 8 }>: Protect,
    Guard<{ E as usize <= std::mem::size_of::<T>() * 8 }>: Protect,
{
    type Output = FixedPoint<???, T>;
    fn add(self, rhs: FixedPoint<E, T>) -> Self::Output {
        todo!()
    }
}

The Output type should have max(D, E) bits after the point, so I tried a const fn:

const fn const_max(a: u8, b: u8) -> u8 {
    if a > b {
        a
    } else {
        b
    }
}
// --snip-- 
type Output = FixedPoint<{ util::const_max(D, E) }, T>;
// --snip--

However this way the compiler can't know that the result of const_max will satisfy the Guard.
Is there any way to make this work without removing the Guard?
Or is there a better way to do the compile-time check of D?

mild violet
# bold thorn I am writing a library for fun, which will include a FixedPoint struct for fixed...

I think you could do it using https://github.com/rust-lang/rust/issues/112792 to add the where clause, not sure of anything else.

GitHub

This is a tracking issue for the feature lazy type aliases. It's considered to be a “sophisticated bug fix” for #21903, hence no RFC. The feature gate for the issue is #![feature(lazy_type_alia...

bold thorn
#

Thanks, I got it to work by simply adding another bound to the impl block, this is the final result for anyone wondering:

impl<const D: u8, const E: u8, T> Add<FixedPoint<E, T>> for FixedPoint<D, T>
where
    T: Shr<u8, Output = T> + Add<T, Output = T> + Copy,
    Guard<{ D as usize <= std::mem::size_of::<T>() * 8 }>: Protect,
    Guard<{ E as usize <= std::mem::size_of::<T>() * 8 }>: Protect,
    Guard<{ util::const_max(D, E) as usize <= std::mem::size_of::<T>() * 8 }>: Protect,
{
    type Output = FixedPoint<{ util::const_max(D, E) }, T>;

    fn add(self, rhs: FixedPoint<E, T>) -> Self::Output {
        todo!()
    }
}