Generic Definition of Iterator of Struct


#1

I want to create a function that takes as a parameter an Iterator over a struct. Here’s an example (playground here: https://play.rust-lang.org/?gist=f672f43cda305f9e9817fa754c00383f&version=stable):

struct foo {
    bar: u64
}

fn want_foo_iter<I>(foo_iter: I)
    where I: Iterator,
          I::Item: foo
{ }

The compiler complains because foo isn’t a trait… so how do I specify that I want an Iterator of struct foo?


#2

play


#3

Ah, so you can specify the Item as a struct when used like Iterator<Item=foo>, but not the way I had it. Got it, but not overly sure why… what is the difference in syntax? Thanks!


#4

I::Item: <...> is a bound for the Item type itself - you want a bound on I however.


#5

One more (hopefully) hang-up with Iteartors and references: (playground here: https://play.rust-lang.org/?gist=db3e31a81fd658101e25112217984c6b&version=stable)

fn want_iter(it: &mut Iterator<Item=Bar>) { }

fn main() {
    let map = BTreeMap::new();
    
    want_iter(&mut map.values());
}

Results in this error. I don’t understand where &Bar is coming from as my Item for the Iterator for want_iter is clearly just Bar, and even Values<'_, &str, Bar> doesn’t a have a reference to Bar:

error[E0271]: type mismatch resolving `<std::collections::btree_map::Values<'_, &str, Bar> as std::iter::Iterator>::Item == Bar`
  --> src/main.rs:16:15
   |
16 |     want_iter(&mut map.values());
   |               ^^^^^^^^^^^^^^^^^ expected reference, found struct `Bar`
   |
   = note: expected type `&Bar`
              found type `Bar`
   = note: required for the cast to the object type `std::iter::Iterator<Item=Bar>`

#6

Values implements Iterator<Item=&V> so it yields references but your signature asked for an iterator that yields values. So you’d want:

fn want_iter<'a>(it: &mut Iterator<Item=&'a Bar>) { }

Any reason you’re using a trait object for the iterator? Typically you can abstract over whether an iterator internally contains refs or values using generics. But not sure if you need/want trait objects on purpose here.


#7

I don’t need a trait object… I’m just looking for something that I can call .next() on and get a Bar that I’m then going to serialize and write to disk.

How would I abstract over if Item is a reference or not, while still requiring it be a struct of type Bar?


#8

Here is how I’d write it. Let me know if you have questions.


#9

Ah, I did not know about Borrow, thanks!