我正在开发我的第一个Rust板条箱,我想通过同时允许foo(vec!["bar", "baz"])
和foo(vec![String::from("foo"), String::from("baz")])
使我的API更加用户友好。
到目前为止,我已经设法接受了String
和&str
,但是我一直在努力为Vec<T>
做同样的事情。
fn foo<S: Into<String>>(string: S) -> String {
string.into()
}
fn foo_many<S: Into<String>>(strings: Vec<S>) -> Vec<String> {
strings.iter().map(|s| s.into()).collect()
}
fn main() {
println!("{}", foo(String::from("bar")));
println!("{}", foo("baz"));
for string in foo_many(vec!["foo", "bar"]) {
println!("{}", string);
}
}
我得到的编译器错误是:
error[E0277]: the trait bound `std::string::String: std::convert::From<&S>` is not satisfied
--> src/main.rs:6:30
|
6 | strings.iter().map(|s| s.into()).collect()
| ^^^^ the trait `std::convert::From<&S>` is not implemented for `std::string::String`
|
= help: consider adding a `where std::string::String: std::convert::From<&S>` bound
= note: required because of the requirements on the impl of `std::convert::Into<std::string::String>` for `&S`
答案 0 :(得分:4)
这不起作用,因为您的迭代没有给您S
,而是&S
。
如果要将字符串从向量中移出,则必须使其可变并耗尽:
fn foo_many<S: Into<String>>(mut strings: Vec<S>) -> Vec<String> {
strings.drain(..).map(|s| s.into()).collect()
}
答案 1 :(得分:4)
您可以使用完全泛型,而不必强迫用户使用Vec
,更好的是,您可以采用实现IntoIterator
的泛型类型,而只需编写{{ 1}}实现Into<String>
,其语法有些奇怪且逻辑合理。您需要第二个通用类型来执行此操作。我将Item
称为迭代器,将T称为Item类型。
I
这解决了您的问题,并使您的功能更加通用。