Преобразовать Vec <String> в фрагмент & str в Rust?
Per Стив Клабник записывает в документации до Rust 1.0 разницу между String
и &str
, в Rust вы должны используйте &str
, если вам действительно не требуется владение над String
. Точно так же рекомендуется использовать ссылки на срезы (&[]
) вместо Vec
, если вам действительно не требуется владение над Vec
.
У меня есть Vec<String>
, и я хочу написать функцию, которая использует эту последовательность строк, и ей не нужно владение над экземплярами Vec
или String
, должна ли эта функция принимать &[&str]
? Если да, то какой лучший способ ссылаться на Vec<String>
на &[&str]
? Или это избыточное принуждение?
Ответы
Ответ 1
Вы можете создать функцию, которая принимает как &[String]
, так и &[&str]
, используя AsRef
trait:
fn test<T: AsRef<str>>(inp: &[T]) {
for x in inp { print!("{} ", x.as_ref()) }
println!("");
}
fn main() {
let vref = vec!["Hello", "world!"];
let vown = vec!["May the Force".to_owned(), "be with you.".to_owned()];
test(&vref);
test(&vown);
}
Ответ 2
Это фактически невозможно без выделения памяти 1.
Дело в том, что переход от String
до &str
- это не просто просмотр бит в другом свете; String
и &str
имеют разный макет памяти, и поэтому переход от одного к другому требует создания нового объекта. То же самое относится к Vec
и &[]
Поэтому, хотя вы можете перейти от Vec<T>
в &[T]
и, следовательно, от Vec<String>
до &[String]
, вы не можете напрямую перейти от Vec<String>
в &[&str]
:
- либо принять, чтобы использовать
&[String]
- или выделите новый
Vec<&str>
, ссылающийся на первый Vec
, и преобразуйте его в &[&str]
1 Требуемое преобразование невозможно, однако с использованием дженериков и привязки AsRef<str>
, как показано в @aSpex, вы получите немного более подробное объявление функции с гибкостью, о которой вы просили.