Reputation: 343
In Rust, how can I pass a vector of owned objects to a function that expects a vector of borrowed objects? Is my only option to create a new vector?
What is the best practice for the signature of a function in which I care about the type of the contained generic of a struct but don't care about if it is borrowed or not?
Example situation:
fn using_vec_of_borrows(borrows: &Vec<&String>) {
//...
}
fn main() {
let foo: Vec<String> = Vec::new();
using_vec_of_borrows(&foo);
}
How could I write using_vec_of_borrows()
so that it accepts a vector of borrowed strings or a vector of owned strings? Or if it was part of an external library, could I convert my vector of owned strings to a vector of borrowed strings without iterating over it?
Keep in mind here that String
is just used as an example type. It could be anything.
Upvotes: 2
Views: 1473
Reputation: 60052
Quoting @trent from this answer:
When you hear "generic over references and non-references", think
Borrow<T>
.
Making your function generic over elements that implement Borrow<String>
will allow it to accept both a &Vec<String>
and &Vec<&String>
:
use std::borrow::Borrow;
fn using_vec_of_borrows<T: Borrow<String>>(borrows: &[T]) {
//...
}
fn main() {
let foo: Vec<String> = Vec::new();
using_vec_of_borrows(&foo);
let foo: Vec<&String> = Vec::new();
using_vec_of_borrows(&foo);
}
You can even change it to an iterator for more flexibility if the elements don't need to be contiguous.
Note: I changed the signature from &Vec<T>
to &[T]
since the latter is more idiomatic. And I would've changed Borrow<String>
into Borrow<str>
for a similar reason, but &String
does not implement Borrow<str>
.
See also:
Upvotes: 4