Abstract over &T and T

I'm trying to abstract over &T and T, so that I can write generic functions to deal with &T and T at the same time. And, I want to avoid unnecessary copy and runtime overhead, so Borrow<T> and Cow<T> are not good enough. I have problem when dealing with match, I don't know how to abstract it, so I came up with a suboptimal solution, that is, add a recovery method to the trait which returns a Cow<T> so I can do match manually. And I think this solution will not sacrifice performance because compiler is able to optimize out the conversion. But still, it's not the optimal solution. So do you have any idea that will help?

use std::borrow::Cow;

trait CopyOnNeed<T> {
    fn borrow(&self) -> &T;
    fn own(self) -> T;
    fn to_cow(self) -> Cow<T>;
}

impl<'a, T:Clone> CopyOnNeed<T> for &'a T {
    fn borrow(&self) -> &T {
        self
    }

    fn own(self) -> T {
        self.clone()
    }

    fn to_cow(self) -> Cow<T> {
        Cow::Borrowed(self)
    }
}

impl<T> CopyOnNeed<T> for T {
    fn borrow(&self) -> &T {
        self
    }

    fn own(self) -> T {
        self
    }

    fn to_cow(self) -> Cow<T> {
        Cow::Owned(self)
    }
}

Can you clarify this point? My go to solution would be a Borrow<T: ToOwned> bound and I don't understand what runtime overhead that would introduce.

You will always do a clone even the caller can forword the ownership to you.

fn f_borrow(a: &A) -> A {
  a.clone()
}

fn f_owned(a: A) -> A {
  a
}

fn f<T: Clone + Borrow<A>>(t: T) -> A {
  t.clone()
}

I see. I think your trait is fine if you need to use the owned type, but I think the borrowing type is usually sufficient (you can still call &self methods) and will result in less cloning.

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.