Я хочу написать одну функцию, которая принимает &str, String и заимствованный &String. Я написал следующие 2 функции:
fn accept_str_and_ref_string(value: &str) {
println!("value: {}", value);
}
fn accept_str_and_string<S: Into<String>>(value: S) {
let string_value: String = value.into();
println!("string_value: {}", string_value);
}
fn main() {
let str_foo = "foo";
let string_foo = String::from("foo");
accept_str_and_ref_string(str_foo);
accept_str_and_ref_string(&string_foo);
accept_str_and_string(str_foo);
accept_str_and_string(string_foo);
}
Можно ли реализовать одну функцию, чтобы я мог это сделать:
accept_all_strings(str_foo);
accept_all_strings(&string_foo);
accept_all_strings(string_foo);
Да, вы правы, я протестировал его с текущей версией Rust 1.36.


Вы можете использовать трейт AsRef<str>:
// will accept any object that implements AsRef<str>
fn print<S: AsRef<str>>(stringlike: S) {
// call as_ref() to get a &str
let str_ref = stringlike.as_ref();
println!("got: {:?}", str_ref)
}
fn main() {
let a: &str = "str";
let b: String = String::from("String");
let c: &String = &b;
print(a);
print(c);
print(b);
}
Функция print будет поддерживать любой тип, реализующий AsRef<str>, включая &str, String и &String.
@trentcl A String не будет скопирован, право собственности на него будет передано методу, если вы не используете ссылку.
Моя ошибка, мой мозг смешал тело примера ОП с вашей подписью.
Что, если функции в конечном итоге потребуется собственная строка, а не ссылка?
@malthe Лично я обычно просто использую stringlike.as_ref().to_string(), так как мне нравится иметь одну и ту же подпись независимо от того, нужна ли мне собственная или заимствованная строка. Я думаю, что это может быть немного неэффективно с аргументами, которые уже принадлежат строкам, поэтому, если вы хотите избежать этого, вы можете использовать другие черты, такие как S: Into<String>.
Похоже, начиная с Rust 1.35.0 вариант
Into<String>также работает для&String.