Explicit lieftime name in type parameter of trait

I have the following types (basically a vector that only returns references and a type with 2 vecors that returns a tuple of references:

struct VecValues<A> {
    values: Vec<A>
}

impl<A> VecValues<A> {
    fn get(&self, index: usize) -> &A {
        &self.values[index]
    }
}

struct ZippedValues<A,B> {
    first: Vec<A>,
    second: Vec<B>,
}

impl<A,B> ZippedValues<A,B> {
    fn get(&self, index: usize) -> (&A,&B) {
        (&self.first[index], &self.second[index])
    }
}

Now I want to "unite" these in a trait (so that I can give it to other types):

trait Values {
    type Item;
    fn get(&self, index: usize) -> Self::Item;
}

Now I am trying to implement this types:

impl<A> Values for VecValues<A> {
    type Item = &A;

    fn get(&self, index: usize) -> Self::Item {
        self.get(index)
    }
}

impl<A,B> Values for ZippedValues<A,B> {
    type Item = (&A,&B);

    fn get(&self, index: usize) -> Self::Item {
        self.get(index)
    }
}

But that does not work:

29 |     type Item = &A;
   |                 ^ explicit lifetime name needed here

But I don't know how and where to insert the lifetime.

And I am a newbie and don't know if this approach makes sense at all :).

Thanks for your help and time!
Nathan

You must tell the lifetime to compiler explicitly using generic lifetimes or 'static, so this

impl<A> Values for VecValues<A> {
    type Item = &A;

    fn get(&self, index: usize) -> Self::Item {
        self.get(index)
    }
}

turns into something like this (not tested)

impl<'a, A> Values for VecValues<A> {
    type Item = &'a A;

    fn get(&self, index: usize) -> Self::Item {
        self.get(index)
    }
}

Hallo Miiao, thanks for your reply.

If I do that I get:

28 | impl<'a, A> Values for VecValues<A> {
   |      ^^ unconstrained lifetime parameter

Try this

Lifetime elision helps us here

But then I cannot implement ZipValues so that it returns (&A,&B) (because it then must return a reference).

But with your tips I found a solution:

trait Values<'a> {
    type Item: 'a;
    fn get(&'a self, index: usize) -> Self::Item;
}

struct VecValues<A> {
    values: Vec<A>
}

impl<A> VecValues<A> {
    fn get(&self, index: usize) -> &A {
        &self.values[index]
    }

    pub fn from_vec(values: Vec<A>) -> VecValues<A> {
        VecValues {
            values
        }
    }

    pub fn zip_values<B>(self, second: Vec<B>) -> ZipValues<A,B> {
        ZipValues::from_vecs(
            self.values,
            second,
        )
    }
}

impl<'a, A: 'a> Values<'a> for VecValues<A> {
    type Item = &'a A;

    fn get(&'a self, index: usize) -> Self::Item {
        self.get(index)
    }
}

struct ZipValues<A,B> {
    first: Vec<A>,
    second: Vec<B>,
}

impl<A,B> ZipValues<A,B> {
   fn get(&self, index: usize) -> (&A, &B) {
       (&self.first[index], &self.second[index])
   }

    pub fn from_vecs(first: Vec<A>, second: Vec<B>) -> ZipValues<A,B> {
        ZipValues {
            first,
            second
        }
    }
}

impl<'a, A: 'a, B: 'a> Values<'a> for ZipValues<A, B> {
    type Item = (&'a A, &'a B);

    fn get(&'a self, index: usize) -> Self::Item {
        self.get(index)
    }
}
1 Like

Oh, I finally understood what you meant. Seems like it’s too late so I’m just proud of you. Good luck

1 Like

Thanks for your time and expertise!

1 Like

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.