繁体   English   中英

如何为自定义IntoIterator :: Item实现std :: fmt :: Display?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM