LimitedFifoQueue
是一个结构,它包含VecDeque
的功能,以限制它随时存储的项目数:
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();
}
}
我已按照以下方式实施IntoIterator
特征:
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()
}
}
一个简化的函数循环并打印每个项目:
fn print_all<I>(lines: &I) where I: IntoIterator {
for string in lines.into_iter() {
println!("{}", string);
}
}
这给了我以下错误:
println!("{}", string);
^^^^^^ the trait `std::fmt::Display` is not implemented for `<I as std::iter::IntoIterator>::Item`
我创建了一个带有完整堆栈跟踪here的代码的游乐场。
另外,我知道可能有更好的方法来完成我想要做的事情。我很乐意听到任何其他建议。
答案 0 :(得分:3)
如何为自定义
std::fmt::Display
实施IntoIterator::Item
?
你做不到。 Item
可能是您不拥有的类型,Display
是您不拥有的特质。 You cannot implement a trait you don't own for a type you don't own
您所能做的就是要求Item
实施Display
:
fn print_all<I>(lines: I)
where I: IntoIterator,
I::Item: fmt::Display,
{
for string in lines.into_iter() {
println!("{}", string);
}
}
您不需要在数据结构或其方法上使用任何其他T: Display
边界,因为这些实现都不会打印出值。
顺便说一句,{for-loops参数会自动调用into_iter
,所以你只需说:
fn print_all<I>(lines: I)
where I: IntoIterator,
I::Item: fmt::Display,
{
for string in lines {
println!("{}", string);
}
}
您可能还希望审核How to implement Iterator and IntoIterator for a simple struct?,因为您将&lfq
传递到print_all
,但&LimitedFifoQueue
并未实施IntoIterator
, LimitedFifoQueue
。这些是不同的类型。你需要像
impl<'a, T> IntoIterator for &'a LimitedFifoQueue<T> {
type Item = &'a T;
type IntoIter = vec_deque::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.store.iter()
}
}
答案 1 :(得分:2)
此问题与您的IntoIterator
实施或其他类型定义无关。请看一下这段代码:
fn print_all<I>(lines: &I) where I: IntoIterator {
for string in lines.into_iter() {
println!("{}", string);
}
}
这段代码甚至不知道您的LimitedFifoQueue
类型!它采用泛型I
的值。我们对I
了解多少?它实现了IntoIterator
。太好了,这告诉我们迭代器吐出的值是什么?没事!
所以它可能是任何东西,特别是那些没有实现fmt::Display
的东西。所以我们要做的是注释迭代器的项至少应该实现fmt::Display
。怎么做的?通过向Item
特征的关联类型IntoIterator
添加绑定:
fn print_all<I>(lines: &I)
where I: IntoIterator,
I::Item: fmt::Display,
{ ... }
一旦你明白你也可以为相关项添加界限,这是直观的。
修复该错误后,将报告另一个错误,即&#34;移出借来的内容&#34;。这是一个相当标准的错误,我在这里不会详细解释。但总结一下:您的print_all()
函数应该收到I
而不是&I
。