将切片作为IntoIterator传递

3

我有一个函数,其签名如下:

pub fn history<'a, I: IntoIterator<Item = &'a str>>(&self, _: I)

稍后,我有一个包含名为main的字段的结构体,该字段是一个装箱的闭包。

main: box |args: &[&str], shell: &mut Shell| {
    shell.history.history(args);
},

重要的是我使用了我展示签名的函数,并将&[&str]作为参数进行调用。我得到了以下编译错误:
src/main.rs:281:47: 281:54 error: type mismatch resolving `<&[&str] as core::iter::IntoIterator>::Item == &str`:
 expected &-ptr,
    found str [E0271]
src/main.rs:281         shell.history.history(args);

显然,&[&str]不能作为IntoIterator使用。我尝试了shell.history.history(args.into_iter());,但是收到了类似的错误信息。

奇怪的是,shell.history.history(args.iter().map(|s|*s));可以工作。不过这似乎并不是正确的解决方案。

1个回答

4

让我们来看一下有关 如何为切片实现IntoIterator 的内容:

impl<'a, T> IntoIterator for &'a [T]
    type Item = &'a T
    type IntoIter = Iter<'a, T>
    fn into_iter(self) -> Iter<'a, T>

请注意,Item被定义为对T的引用,其中T是切片中项目的类型。由于您有一个&str片段,这意味着Item&&str
您可以使用.map(| s | * s)来取消引用外部引用并生成&str迭代器。
另一个解决方案是将您的history函数泛化为接受I:IntoIterator<Item = &'a str>I:IntoIterator<Item = &'b&'a str>。为了做到这一点,我们需要一个同时实现&'a str&'b&'a str的特征。我们可以使用AsRef<str>来实现这一点(感谢Vladimir Matveev指出)。
pub fn history<I>(i: I)
where
    I: IntoIterator,
    I::Item: AsRef<str>,
{
    for s in i {
        println!("{}", s.as_ref());
    }
}

fn main() {
    history(&["s"]);
}

1
@FrancisGagné 不能使用 AsRef<str> 替代自定义的 IntoStrSlice 吗? - Vladimir Matveev
1
确实,它可以工作 - Vladimir Matveev
1
我不知道 AsRef 可以这样使用!已编辑。 - Francis Gagné
@user1685095,您是指 where I::Item: AsRef<T>, T: Debug(其中 T 是第二个泛型类型),还是指 where I::Item: AsRef<str> + Debug - Francis Gagné
@FrancisGagné 我的意思是,将项目转换为引用后,可以使用调试格式化程序进行格式化。 - user1685095
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接