【问题标题】:How to accept both Vec<String> and Vec<str> as function arg in Rust如何在 Rust 中同时接受 Vec<String> 和 Vec<str> 作为函数 arg
【发布时间】:2019-07-26 16:01:03
【问题描述】:

我正在开发我的第一个 Rust crate,我希望通过同时允许 foo(vec!["bar", "baz"])foo(vec![String::from("foo"), String::from("baz")]) 使我的 API 更加用户友好。

到目前为止,我已经设法同时接受 String&amp;str,但我正在努力为 Vec&lt;T&gt; 做同样的事情。

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`

【问题讨论】:

标签: string generics vector rust


【解决方案1】:

你可以选择完整的泛型,你不需要强制用户使用Vec,更好的是你可以使用实现IntoIterator的泛型类型,你只需要编写Item实现@987654322 @,语法有点奇怪和逻辑。您需要第二种泛型类型来执行此操作。我将 I 称为迭代器类型,将 T 称为 Item 类型。

fn foo<S: Into<String>>(string: S) -> String {
    string.into()
}

fn foo_many<I, T>(iter: I) -> Vec<String>
where
    I: IntoIterator<Item = T>,
    T: Into<String>,
{
    iter.into_iter().map(Into::into).collect()
}

fn main() {
    println!("{}", foo(String::from("bar")));
    println!("{}", foo("baz"));

    for string in foo_many(vec!["foo", "bar"]) {
        println!("{}", string);
    }

    for string in foo_many(vec![foo("foo"), foo("baz")]) {
        println!("{}", string);
    }
}

这解决了您的问题并使您的功能更加通用。

【讨论】:

  • 我什至没有想过允许其他可迭代结构,但这绝对是一个更灵活的解决方案!谢谢。
【解决方案2】:

这不起作用,因为您的迭代没有给您S,而是&amp;S

如果你想字符串移出向量,你必须让它可变并排空它:

fn foo_many<S: Into<String>>(mut strings: Vec<S>) -> Vec<String> {
    strings.drain(..).map(|s| s.into()).collect()
}

playground

【讨论】:

  • @MartinSotirov 我添加了指向操场的链接。我错过了什么吗?
  • 抱歉,我错过了链接。这正是我需要的。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-01
  • 2019-11-10
  • 2017-02-21
  • 2021-11-30
相关资源
最近更新 更多