Say we have:
struct Foo {
string: String
}
impl Foo {
fn new(thing: ?) -> Foo {
let string: String = thing.magic();
Foo { string }
}
}
If thing
is a String
already, I'd like to claim ownership as-is without a clone. If it's some other kind of string-like object, I'd like to to_string()
it (etc.) to produced an owned version. I'm sure there's a Trait or wrapper type in std
for this, I'm just not sure what it is. ToString
doesn't seem right, as that clones the String
if it was already a String
.
Thoughts? Thanks you kindly.
Cow<'a, str>
.
use std::borrow::Cow;
fn f(s: Cow<'_, str>) {
let s = s.into_owned();
// You have a String now
}
Edit: Correction by @Hyeonu , thanks.
Hyeonu
December 16, 2020, 3:34am
3
Actually it's Cow::into_owned()
. .to_owned()
invokes the implementation of the str
by autoderef, so it always allocate.
1 Like
How about on the caller's end, though? Is there a Trait that allows Foo::new()
to accept string literals as-is?
On the caller's end with Cow
you need .into()
. This works instead though:
fn foo<'a, S: Into<Cow<'a, str>>>(s: S) {
let s = s.into().into_owned();
// You have a String now
}
fn main() {
foo("foo");
foo("bar".to_string());
}
Which would in theory work too if they in turn had an owned String
from elsewhere, and were passing it down to me as-is. Thank you, I will try this out.
2e71828
December 16, 2020, 4:54am
7
The intermediate Cow
isn’t necessary: &str
and String
both implement Into<String>
:
fn foo<'a, S: Into<String>>(s: S) {
let s = s.into();
// You have a String now
}
fn main() {
foo("foo");
foo("bar".to_string());
}
5 Likes
Heh, derp. Failed to get off my thought train.
Ah ha, so no cow-tipping necessary. Okay, thanks folks! My understanding of From
and Into
are still a bit hazy, so I'll read up on them.
Ah looks like this does the right thing due to blanket implementations.
impl<T> From<T> for T {
fn from(t: T) -> T {
t
}
}
So converting something to itself always transfers ownership and doesn't clone. Then:
impl<T, U> Into<U> for T
where
U: From<T>,
{
fn into(self) -> U {
U::from(self)
}
}
where T
and U
are both String
, and we're all good.
system
Closed
March 16, 2021, 6:41am
11
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.