genericsrustgeneric-const-exprs

Calling different generics in a loop


While this is a trivial example, I have multiple generic functions which need to work across a few dozen possible values. The actual value is not known until runtime, as it is provided as an argument.

#![feature(generic_const_exprs)]

fn generic_division<const DIVISOR: u64>(denominator: u64) -> u64 {
    denominator / DIVISOR
}

fn main() {
    let denominator = 12;
    for i in 1..5 {
        let dividend = match i {
            1 => generic_division::<1>(denominator),
            2 => generic_division::<2>(denominator),
            3 => generic_division::<3>(denominator),
            4 => generic_division::<4>(denominator),
            _ => panic!()
        };
        println!("{} / {} == {}", denominator, i, dividend);
    }
}

Is there a better way than above? All other approaches have run into const issues.


Solution

  • When you use const generic parameter, intent is to guarantee that parameter is known at compile time. Its not even syntactically possible to pass runtime value here. If you want to ensure your function can be constant folded and also accept runtime values, if needed, you can use const fn. Lets give an example.

    // prefixing function with const
    const fn const_divisor(value: u64, divisor: u64) -> u64 {
        value / divisor
    }
    
    // no difference compared to non const fn
    fn main() {
        let denominator = 12;
        for i in 1..5 {
            let dividend = const_divisor(denominator, i);
            println!("{} / {} == {}", denominator, i, dividend);
        }
    }
    
    // the advantage of const fn is that you can use it in constants
    const REAL_USECASE: u64 = const_divisor(1024, 46);