A confusing problem about generic

I meet a strange problem, please help. the code as following.

    pub trait Measure<T, R> {
        fn distance(a: &T, b: &T)-> R;
    }
    pub struct Sample<T, R, M> where M: Measure<R> {
        data: Vec<T>,
        attr_num: usize,
        distance_op: M,
    }

but compile error:

error[E0392]: parameter `R` is never used
  --> src\material.rs:42:26
   |
42 |     pub struct Sample<T, R, M> where M: Measure<R> {
   |                          ^ unused parameter
   |
   = help: consider removing `R`, referring to it in a field, or using a marker such as `PhantomData`

error: aborting due to previous error

please help, thanks

You can just omit it from the struct and only include it on the impl block.

pub struct Sample<T, M> {
    data: Vec<T>,
    attr_num: usize,
    distance_op: M,
}

impl<T, M, R> Sample<T, M>
where
    M: Measure<R>
{
    ...
}
2 Likes

still compilation error

error[E0207]: the type parameter `R` is not constrained by the impl trait, self type, or predicates
  --> src\material.rs:47:17
   |
47 |     impl <T, M, R> Sample <T, M>
   |                 ^ unconstrained type parameter

error: aborting due to previous error

please help, thanks

Good point. You actually have to introduce it on every method that uses R in the argument types or the return type. E.g.:

impl<T, M> Sample<T, M>
{
    fn foo<R>(&self) -> SomeTypeWith<R>
    where
        M: Measure<R>
    {
        ...
    }
}

I see. In that case you probably want a PhantomData

2 Likes

Another option is to make R an associated type to the trait instead of a parameter:

pub trait Measure<T> {
    type Result: Default + std::ops::AddAssign;
    fn distance(&self, a: &T, b: &T)-> Self::Result;
}
    
pub struct Sample<T, M> {
    data: Vec<T>,
    attr_num: usize,
    distance_op: M,
}

impl<T,M:Measure<T>> Sample<T,M> {
    pub fn len(&self)->M::Result {
        let mut total: M::Result = Default::default();
        let mut iter = self.data.iter();
        if let Some(mut prev) = iter.next() {
            for x in iter {
                total += self.distance_op.distance(prev, x);
                prev = x;
            }
        }
        total
    }
}

(Playground-- I don't know what kind of calculation these objects represent, so I had to take a guess at a reasonable example method)

7 Likes

It works! Thank you very much.

1 Like

Thanks for kindly reply:)

Thanks for kindly reply :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.