以下代码最能说明问题。
use std::iter::IntoIterator;
fn iterate<I: IntoIterator<Item=String>>(v: I) {
}
// iterate(&["foo".to_string()])
// error: type mismatch resolving `<&[collections::string::String; 1] as core::iter::IntoIterator>::Item == collections::string::String`:
// expected &-ptr,
// found struct `collections::string::String` [E0271]
// iterate(["foo".to_string()].iter())
// type mismatch resolving `<core::slice::Iter<'_, collections::string::String> as core::iter::IntoIterator>::Item == collections::string::String`:
// expected &-ptr,
// found struct `collections::string::String` [E0271]
// This works !
iterate(vec!["foo".to_string()])
如何一般地迭代任何东西(使用给定的项目类型)?
目的是允许这样的函数的用户传入任何可以迭代或转换为迭代器的东西。
此外,我感觉实际问题并没有在编译器错误中真正描述 - 因为它看到的类型似乎与它所显示的类型不同。
我正在使用rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)
答案 0 :(得分:8)
让我们看一下第一种情况的类型:
for i in &["foo".to_string()] {
let () = i;
// expected `&collections::string::String`,
// found `()`
}
也就是说,您的函数需要的&String
上的迭代变量类型为String
,不。for i in vec!["foo".to_string()] {
let () = i;
// expected `collections::string::String`,
// found `()`
}
第二种情况也会发生同样的事情。第三种情况有效:
IntoIter
我们可以查看arrays和all 3 forms of Vec的Vec<T>
的实施情况。请注意,&Vec<T>
的实现使用向量,而use std::iter::IntoIterator;
fn iterate<I, S>(v: I)
where I: IntoIterator<Item=S>,
S: AsRef<str>
{}
fn main() {
iterate(&["foo"]);
iterate(&["foo".to_string()]);
iterate(["foo".to_string()].iter());
iterate(vec!["foo".to_string()]);
iterate(&vec!["foo".to_string()]);
}
的实现必须通过对元素的引用返回迭代器。
您不能使用数组,因此迭代器必须始终返回引用。
以下是一个使用AsRef
特征的示例,该特性可以达到您想要的效果:
Iterator
这表示我们期望任何实现特征AsRef<str>
的具体类型。该迭代器必须产生一个实现特征String
的类型,允许我们传入{&str
,{{1}}}的{数组,向量,切片}。