Generic problem: mismatched type

Hi, I wrote a simple generic program to test whether the data (can be any unsigned type) is divided by 3. But compile failed. Any suggestion? Thanks!
(playground)

use std::ops::Rem;

pub struct DividedBy3<T> {
    data: T,
}

impl<T> DividedBy3<T> {
    pub fn new(d: T) -> Self {
        DividedBy3 { data: d }
    }

    pub fn divided_by_3(d: T) -> bool
    where
        T: Rem,
    {
        d % 3 == 0
    }
}

fn main() {
    let d1 = DividedBy3::new(3_u8);
    let d2 = DividedBy3::new(3_u16);
    let d2 = DividedBy3::new(3_u32);
}
error[E0308]: mismatched types
  --> src/main.rs:16:13
   |
7  | impl<T> DividedBy3<T> {
   |      - this type parameter
...
16 |         d % 3 == 0
   |             ^ expected type parameter `T`, found integer
   |
   = note: expected type parameter `T`
                        found type `{integer}`

error[E0369]: binary operation `==` cannot be applied to type `<T as Rem>::Output`
  --> src/main.rs:16:15
   |
16 |         d % 3 == 0
   |         ----- ^^ - {integer}
   |         |
   |         <T as Rem>::Output

The problem is that T needs to be an integer so that you can do integer ops on it. Like % 3. But your generic function only knows that T can be of anything of any type provided it implements the "ToString" trait. Which could be pretty much anything.

I believe people use the num crate to deal with and constrain T to an integer type. I have no actual experience of that though.

2 Likes

(playground)

use std::ops::Rem;

pub struct DividedBy3<T> {
    data: T,
}

impl<T> DividedBy3<T> {
    pub fn new(d: T) -> Self {
        DividedBy3 { data: d }
    }

    pub fn divided_by_3(&self) -> bool
    where
        T: Rem<Output=T> + Default + PartialEq + From<u8> + Copy,
    {
        let three:T = 3.into();
        let zero:T = T::default();
        self.data % three == zero
    }
}

fn main() {
    println!("{}",DividedBy3::new(4_u8).divided_by_3());
    println!("{}",DividedBy3::new(5_u16).divided_by_3());
    println!("{}",DividedBy3::new(6_u32).divided_by_3());
    println!("{}",DividedBy3::new(9_u64).divided_by_3());
}
1 Like