Help with generics

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fceaa2be25e6eef9b627c11b51a7640c

The idea is I have an Attribute trait which I implement for numeric primitives and &str.

trait Attrib {
    type Type;
    fn get() -> Self::Type;
    fn set(val: impl Into<Self::Type>);
}

But I would want get() to return String but set() take &str. The playground code with Into works, but it's an unnecessary allocation.

An easy solution would be to define the trait like this:

trait Attrib {
    type RType;
    type SType;
    fn get() -> Self::RType;
    fn set(val: Self::SType);
}
impl Attrib for &str {
    type SType = &str;
    type RType = String;
    fn get() -> Self::RType { ... }
    fn set(val: Self::SType) { ... } 
}

I was wondering if it's possible to keep a single associated Type but make get and set generic with some mixture of ToOwned and Borrow bounds. I couldn't make anything working.

Where did you get stuck? I would do (playground):

trait Attrib {
    type Type: ?Sized + ToOwned;
    fn get() -> <Self::Type as ToOwned>::Owned;
    fn set(val: &Self::Type);
}

impl Attrib for i32 {
    type Type = i32;
    fn get() -> i32 {
        10
    }
    fn set(val: &i32) {
        let _ = *val;
    }
}

impl Attrib for String {
    type Type = str;
    fn get() -> String {
        "test".to_owned()
    }
    fn set(val: &str) {
        let _ = val;
    }
}
1 Like

Ah, I was pretty close :slight_smile: I started intoducing type parameters to get<T> and set<T> and got lost in the woods. Also the ?Sized for str is the key.
Thank you!

The only downside is that for numeric type it need a reference set::<i32>(&10)

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.