Operations on const generic parameters as a generic parameter

I am trying to impl the Add trait for a vector-like type with wrap around indexing. I want (a + b) to return a vector whose length is the maximum of the lengths of a and b. Here's my attempt which fails.

impl<T: Float, const M: usize, const N: usize>
Add<&ChanVec<T, N>> for &ChanVec<T, M> {
    type Output = ChanVec<T, const max(M, N)>;
    fn add(&self, b: &ChanVec<T, N>) -> Self::Output {
        Output {
            x: array_init(|i| self[i] + b[i]),
        }
    }
}

It doesn't like my const max(M,N), says "expected lifetime, type, or constant, found keyword const". I tried it first without the const and it said "not a type". I tried to extract it by writing const P: usize = max(M,N);, but it says "not a member of trait 'Add'". So, is it possible to return a type with length max of M and N?

Const values are substituted into generic parameters using the {expr} syntax. Furthermore, in order to perform operations on const generic parameters, you will need the nightly toolchain with the generic_const_exprs feature:

#![feature(generic_const_exprs)]

use core::ops::Add;
use num_traits::Float;

const fn max(x: usize, y: usize) -> usize {
    if x < y { y } else { x }
}

struct ChanVec<T, const N: usize>([T; N]);

impl<T, const M: usize, const N: usize> Add<&ChanVec<T, N>> for &ChanVec<T, M>
where
    T: Float,
    [(); max(M, N)]:,
{
    type Output = ChanVec<T, {max(M, N)}>;
    
    fn add(self, b: &ChanVec<T, N>) -> Self::Output {
        todo!()
    }
}

(Playground)

1 Like

Thank you for the solution!

What does this bit mean in the where clause?

it just means that the value is small enough to fit in an allocation. Const values have to be constrained somehow, for some technical reason that I haven't yet bothered to fully go after and understand.