Function with generic struct parameter

Hello guys,

I have a question. Let's suppose that I have multiple structs that I use to hold data. These data are received via UnixDatagram.

In such a case I need to have a function for each struct to get the data eg:

struct A{
    a0 : u8,
    a1 : u8
}

struct B{
    b0 : u8,
    b1 : u8,
    b2 : u8
}

get_data_a(socket : &UnixDatagram, a_inst : A){
....
}
get_data_b(socket : &UnixDatagram, b_inst : B){
....
}

The body of the two above function is pratically the same except the fact that one uses A and the other one B.

Is it possible to have a "get_data" function with a generict type T as parameter ?

Thanks

Sounds like you want a trait.

trait GetData {
    fn get_data(self, socket: &UnixDatagram);
}

impl GetData for A { ... }
impl GetData for B { ... }

Then, if you want to write a function that doesn't care which one of those it gets, then you can use generics:

fn do_thing_with<T: GetData>(socket: &UnixDatagram, inst: T) {
    inst.get_data(socket);
}
1 Like

Hello Daniel !

BTW it seems that I need to write the specific function as impl for each structure correct ?

I was hoping to avoid it and write just the "generic" version.

Thanks !

F.

Can you show

?

If the there's a common functionality which is covered by a trait, it might be possible to have a single function body implementation.

If there's not, you could probably employ a macro instead.

1 Like

Hi !

Suppose for example that:

get_data_a( c : &UnixDatagram. a : A){
    println!("{}",std::mem::size_of::<A>())
}
get_data_b( c : &UnixDatagram. b : B){
    println!("{}",std::mem::size_of::<B>())
}

I was wondering about having a function with a generic type T like

get_data( c : &UnixDatagram. t : T){
   println!("{}",std::mem::size_of::<T>())
}

BTW it seems that if I want to use a trait, I jave to define both "get_data_a" and "get_data_b" as A/B impl get_data functions. Am I right ?

I'm a rust newbie and I'm not very confident with the langueage. Som forgive me if I say something odd !

thanks

The problem is that this example is so simple that, yeah, you can just use a trivial generic function. But this is almost never the case in practice. If the implementation depends on the type in any way whatsoever (like accessing fields even if they have the same name) then you're either going to have to use existing traits with the functionality you need, or define your own.

Pretty much. The trait doesn't need to be the entire function, though. If the two functions are nearly identical, then you can potentially just abstract the differences into a trait, then define get_data<T: SomeWellNamedTrait> based on that trait.

It's fine so long as you cancel it out with another odd thing, then we're even.

1 Like

This is not possible at the moment, as traits and generic items don't capture the fields of a structure for the time being. A more complex but achievable approach would be to implement a proxy trait for it, for example:

struct A {
    field_pub: i32,
}
struct B {
    field_pub: i32,
    field_priv: usize,
}

trait FieldPubGet {
    fn get_field_pub(&self) -> i32;
}

impl FieldPubGet for A {
    fn get_field_pub(&self) -> i32 {
        &self.field_pub
    }
}

impl FieldPubGet for B {
    fn get_field_pub(&self) -> i32 {
        &self.field_pub
    }
}

fn do_something<T: FieldPubGet>(val: &T) -> i32 {
    val.get_field_pub()
}

(If there are too many fields to handle, you can also use macros to help with that, but that's a matter of practice.)

But if you do want to get the fields of a generic element, that's currently not possible, at least under stable. If I remember correctly, rustc has a feature for fields in traits, although I don't remember if it's already fixed functionality or if it's in early experimental stages.

Edit: Related papers:

fields-in-traits-rfc/0000-fields-in-traits.md 和主 ·Nikomatsakis/fields-in-traits-rfc --- fields-in-traits-rfc/0000-fields-in-traits.md at master · nikomatsakis/fields-in-traits-rfc (github.com)
Allow fields in traits that map to lvalues in impl'ing type by nikomatsakis · Pull Request #1546 · rust-lang/rfcs (github.com)
Fields in Traits - language design - Rust Internals (rust-lang.org)

1 Like

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.