0
fn main() {
    
    fn calculate_two_numbers<T:Debug, const N: usize>(data_set: [T;N]) -> (i32,i32) {
        
        // Key Code 
        let a = &data_set[0]+&data_set[1];
        println!("{:?},{:?},{:?}",&data_set[0],&data_set[1],a);
        
        // Ignore
        return (0,0)
    }

let data = [1509,1857,1736,1815,1576];
let result = calculate_two_numbers(data);
}

I have a very simple function which takes a list of size n.

From this list, I want to take the first two variables and add them together. I then want to print all of them out with println!.

However, I get the error error[E0369]: cannot add &T to &T

This is the solution the complier suggests but I have trouble understanding it

fn calculate_two_numbers<T:Debug + std::ops::Add<Output = &T>, const N: usize>(data_set: [T;N])

Can someone explain what std::ops::Add<Output = &T> does?

Gunty
  • 1,841
  • 1
  • 15
  • 27
  • 1
    First of all just use `data_set[0]+data_set[1]`. `Add` is a trait. You say that `T` has this trait, that is `T` has an operation `T + T` that in turn produces `T` value – Alexey S. Larionov Nov 15 '21 at 07:22
  • Possible duplicate: https://stackoverflow.com/questions/34630695/how-to-write-a-trait-bound-for-adding-two-references-of-a-generic-type – Jerboas86 Nov 15 '21 at 08:31

1 Answers1

1

In Rust, when using generic types, you need to tell the compiler what kind of operations you would want to do with the type. This is done be constraining the bounds of your type (You are already using it with Debug, it means you can use it as it were a debug type).

The compiler suggest to add the Add trait, but it will not really work straight away because of the references. You can either add a lifetime or use Copy (with would be probably desirable if you are gonna work with numbers), again add it as another bound:

use std::fmt::Debug;
use std::ops::Add;

fn calculate_two_numbers<T: Debug + Add::<Output=T> + Copy, const N: usize>(data_set: [T; N]) -> (i32, i32) {
    // Key Code
    let a = data_set[0] + data_set[1];
    println!("{:?},{:?},{:?}", data_set[0], data_set[1], a);

    // Ignore
    return (0, 0);
}

fn main() {
    let data = [1509, 1857, 1736, 1815, 1576];
    let result = calculate_two_numbers(data);
}

Playground

If using the references approach, you need to specify that for any lifetime for your references that reference implements Add<Output=T>:


fn calculate_two_numbers<T: Debug, const N: usize>(data_set: [T; N]) -> (i32, i32)
where
    for<'a> &'a T: Add<Output = T>,
{
    // Key Code
    let a = &data_set[0] + &data_set[1];
    println!("{:?},{:?},{:?}", data_set[0], data_set[1], a);

    // Ignore
    return (0, 0);
}

Playground

Netwave
  • 40,134
  • 6
  • 50
  • 93