[英]How can I implement std::fmt::Display for a custom IntoIterator::Item?
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`
我创建的代码的操场采用了全堆栈跟踪这里 。
另外,我知道可能会有更好的方法来完成我尝试做的事情。 我希望听到其他建议。
如何为自定义
IntoIterator::Item
实现std::fmt::Display
?
你不能。 Item
可能是您不拥有的类型,而Display
是您不拥有的特征。 您不能为您不拥有的类型实现您不拥有的特征 。
您所要做的就是要求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);
}
}
您可能还希望查看如何通过简单的结构实现Iterator和IntoIterator? ,因为您&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()
}
}
此问题与您的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
。 怎么做? 通过向IntoIterator
特性的关联类型Item
添加绑定:
fn print_all<I>(lines: &I)
where I: IntoIterator,
I::Item: fmt::Display,
{ ... }
一旦了解了您还可以将边界添加到关联的项目,就很直观了。
修复该错误后,将报告另一个错误,即“移出借用的内容”。 这是一个相当标准的错误,在此不再详细说明。 但总而言之:您的print_all()
函数应该收到一个I
而不是&I
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.