Determine fn output type from input type

Viewed 74

I would like a function that returns f32 if the input is f32, for all other numeric inputs it should return f64.

A simplified example of the structure is this:

use num::{Num, NumCast, ToPrimitive, traits::Float};

fn example<N: Num + ToPrimitive, T: Float>(input: N) -> T {
    let output = input + N::one();
    NumCast::from(output).unwrap()
}

fn main() {
    println!("{}", example::<f32, f32>(1f32));
    println!("{}", example::<u32, f64>(1u32));
}

is there a way to control the dispatch so that I can drop the turbofish and it will automatically map

f32 -> f32 and

anything else -> f64 ?

1 Answers

You cannot have a function which returns either f32 or f64 making decision in runtime. But you can implement such behavior using traits.

You can have two traits ToF32 and ToF64 and implement first one for f32 only and ToF64 for all other numeric types except f32. You will need a lot of boilerplate code to implement ToF64 though. It can be compacted using macros.

use num::{NumCast, ToPrimitive, one, Integer};

trait ToF32 {
    fn example(self) -> f32;
}

impl ToF32 for f32 {
    fn example(self) -> f32 {
        let output = self + one::<Self>();
        NumCast::from(output).unwrap()
    }
}

trait ToF64 {
    fn example(self) -> f64;
}

impl<T: Integer + ToPrimitive> ToF64 for T {
    fn example(self) -> f64 {
        let output = self + one::<Self>();
        NumCast::from(output).unwrap()
    }
}

fn main() {
    println!("{}", 1f32.example());
    println!("{}", 1u32.example());
}

Playground link

Related