Generic data type in function

fn main()
{
let (a,b) = (10,10);
sum(a,b)
}
fn sum (a:T,b:T)
{
let c = a+b;
println!("{}",c);
}

this code result in error can any one help to solve for the error to find sum of two numbers / and operation using generic in a function

Hi,

to use generic types you would need to define the function to be generic over this type.
Eg:

fn sum<T>(a: T, b: T) {
    let sum = a + b;
    println!("Sum: {:?}", sum)
}

The thing is, that this does not compile as it is not guarantied that the generic type T supports addition as T could be any type.
This would mean that you typically need to add type bounds to this type to ensure that whatever type is passed it supports the required operation like so:

fn sum<T: std::ops::Add>(a: T, b: T) {
    let sum = a + b;
    println!("Sum: {:?}", sum)
}

This still does not compile as it is not ensured that the resulting type of the addition could be formatted using the Debug trait. So we need to add the required type constrain to the result - meanung the output type of the addition. This could be done in a bit more readable fashing using the where clause for generic type definitions like so:

fn sum<T>(a: T, b: T) 
    where T: std::ops::Add,
          <T as std::ops::Add>::Output : std::fmt::Debug 
{
    let sum = a + b;
    println!("Sum: {:?}", sum)
}

fn main() {
    let (a, b) = (10u32, 10u32);
    
    sum(a, b);
}

Now the code compiles - see play ground: Playground

The final function definition of sum says: please be generic over the type T where the actual type passed need to adhere to the following conditions:

  • implement the Add operation
  • implement the Debug trait for the result type of the addition
    Those constrains are typically fulfilled for all number types by default but could be also fulfilled by implementing them for custom types... but this is for another topic :wink:

What if i wand to do multiple operation in side the function
eg: add and sub inside the same function

You would add extra bounds to the generic type parameter like this:

(playground)

fn sum<T>(a: T, b: T) 
    where
        // Enforcing copy means we don't have to worry about using the same value twice
        T: Copy,
        // Enforcing add means the value can be added
        T: std::ops::Add,
        // Enforcing sub means the value can be subtracted
        T: std::ops::Sub,
        // This enforces that the output of the add operation can be debug printed
        <T as std::ops::Add>::Output : std::fmt::Debug,
        // This enforces that the output of the subtract operation can be debug printed
        <T as std::ops::Sub>::Output : std::fmt::Debug
{
    let sum = a + b;
    println!("Sum: {:?}", sum);
    
    let diff = a - b;
    println!("Diff: {:?}", diff);
}

fn main() {
    let (a, b) = (10u32, 10u32);
    
    sum(a, b);
}
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.