LimitedFifoQueue
is a struct that wraps the functionality of a VecDeque
to limit the number of items it will store at any time:
use std::collections::{vec_deque, VecDeque};
use std::fmt;
use std;
#[derive(Debug)]
pub struct LimitedFifoQueue<T> {
size: usize,
store: VecDeque<T>,
}
impl<T> LimitedFifoQueue<T> where T: fmt::Display {
pub fn new(size: usize) -> LimitedFifoQueue<T> {
LimitedFifoQueue {
size: size,
store: VecDeque::with_capacity(size),
}
}
pub fn push(&mut self, elem: T) {
self.store.push_front(elem);
if self.store.len() > self.size {
self.store.pop_back();
}
}
pub fn clear(&mut self) {
self.store.clear();
}
}
I've implemented the IntoIterator
trait as follows:
impl<T> IntoIterator for LimitedFifoQueue<T> where T: fmt::Display {
type Item = T;
type IntoIter = vec_deque::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.store.into_iter()
}
}
And a simplified function that loops through and prints each Item:
fn print_all<I>(lines: &I) where I: IntoIterator {
for string in lines.into_iter() {
println!("{}", string);
}
}
This gives me the following error:
println!("{}", string);
^^^^^^ the trait `std::fmt::Display` is not implemented for `<I as std::iter::IntoIterator>::Item`
I have created a playground of the code with a full stack trace here.
Also, I'm aware that there may be a better way to accomplish what I'm trying to do. I'd love to hear any additional suggestions.
This problem has nothing to do with your
IntoIterator
implementation or the rest of your type definition. Just take a look at this code:This piece of code doesn't even know about your
LimitedFifoQueue
type! It takes a value of generic typeI
. What do we know aboutI
? It implementsIntoIterator
. Great, what does that tell us about the values the iterator will spit out? Nothing!So it could be anything, in particular also stuff that doesn't implement
fmt::Display
. So what we want to do is to annotate that the items of the iterator should at least implementfmt::Display
. How is that done? By adding a bound to the associated typeItem
of theIntoIterator
trait:Once you understand that you can also add bounds to associated items this makes intuitive sense.
After you fixed that error, another error will be reported, about "moving out of borrowed content". This is a fairly standard error, which I won't explain in detail here. But in summary: your
print_all()
function should receive aI
instead of a&I
.You cannot.
Item
might be a type you don't own, andDisplay
is a trait you don't own. You cannot implement a trait you don't own for a type you don't own.All you can do is require that
Item
implementsDisplay
:You don't need any of the other
T: Display
bounds on your data structure or its methods, as none of those implementations care to print out a value.Incidentally,
into_iter
is automatically called on the for-loops argument, so you only need to say:You may also wish to review How to implement Iterator and IntoIterator for a simple struct?, as you are passing
&lfq
intoprint_all
, but&LimitedFifoQueue
doesn't implementIntoIterator
, onlyLimitedFifoQueue
does. These are different types. You'll need something like