如何更普遍地编写采用 IntoIter 的函数

How to write fuctions that takes IntoIter more generally

我正在阅读 Whosebug 问题的答案并尝试修改函数 history 以采用 IntoIter 其中项目可以是任何可以转换为参考并具有某些特征的东西 Debug 在这种情况下。

如果我从函数定义中删除 V: ?Sized,rust 编译器会抱怨它在编译时不知道 str 的大小。

use std::fmt::Debug;

pub fn history<I: IntoIterator, V: ?Sized>(i: I) where I::Item: AsRef<V>, V: Debug {
    for s in i {
        println!("{:?}", s.as_ref());
    }
}

fn main() {
    history::<_, str>(&["st", "t", "u"]);
}

我不明白为什么编译器一开始就显示错误,也不确定如果我用 V: ?Sized.

作弊程序为什么能正常工作

I kind of cheat with V: ?Sized

这不是作弊。默认情况下,所有通用参数都假定为 Sized。这个默认值存在是因为它是最常见的情况——没有它,几乎每个类型参数都必须用 : Sized.

注释

在你的例子中,V 只能通过引用访问,所以它不需要是 Sized。放宽 Sized 约束使您的函数尽可能通用,允许它与大多数可能的类型一起使用。

类型 str 未调整大小,因此这不仅仅是泛化,您实际上需要放宽默认 Sized 约束才能将您的函数与 str 一起使用。