将切片作为IntoIterator传递

时间:2016-02-02 03:13:10

标签: rust

我有一个带有以下签名的函数:

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 个答案:

答案 0 :(得分:3)

我们来看看how IntoIterator is implemented for slices

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: IntoIterator>(_: I)
    where I::Item: AsRef<str>
{
    for s in i {
        println!("{}", s.as_ref());
    }
}

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