Creating struct variants using generics

Hi! I am very new to rust (and programming in general), so I hope you will forgive me if this is a really stupid question or if the answer would have been easy to find.

Anyways, I am wondering if it is possible to get something like this to work:

struct GraphicMatroidElement {
    name:  u32,
    weight: f32,
    nodes: [u32;2],
}
struct GraphicMatroidInpendence {
   // code goes here
}
impl GraphicMatroidInpendence {
   // code goes here
}
struct GraphicMatroid {
    element_type: GraphicMatroidElement,
    independence_info: GraphicMatroidInpendence,
}
// the idea is to create a Matroid struct that is of the GraphicalMatroid variant 
struct Matroid<Var>{
    elements: Vec<Var.element_type>,
    independence: Var.independence_info,
}

I want to be able to create Matroid structs that are of a certain variant. The variant of the Matroid struct is specified by a second struct, e.g. the GraphicMatroid struct above. The variant struct essentially tells the Matroid struct what types its fields should have.

For example, the independence field in a GraphicalMatroid variant of the Matroid struct should be a GraphicMatroidInpendence struct.

Is this in any way possible and am I even making sense here? Any help would be greatly appreciated! :slight_smile:

If the number of variants that you expect are known in advance, you can achieve what you're looking for with an enum. For example:

enum Matroid {
  Graphic {
    elements: Vec<GraphicMatroidElement>,
    independence: GraphicMatroidInpendence,
  }
  ... // Other variants here.
}
1 Like

Thanks for the reply! I think this should work, as I will know the number of variants in advance. However, I would like there to be fields in the Matroid struct that do not depend on the variant, the enum option doesn't really allow for that, right? Also, the enum definition might end up being huuuuuge once there are many variants but that is more of a cosmetic problem.^^

You can't achieve that with enums alone as you said, but you can combine structs and enums to achieve that with a little bit of nesting:

struct Matroid {
    some_field: TypeOfSomeField,
    some_other_field: TypeOfSomeOtherField,
    // Then you put here the actual enum of matroids that will define the elements and independence fields
    variant_specific_fields: YourEnumOfMatroids
}

And if you don't want that to leak to the outside world you can, for example, flatten the serialized representation with Serde:

struct Matroid {
    some_field: TypeOfSomeField,
    some_other_field: TypeOfSomeOtherField,
    // Once serialized, the fields from the enum variants will appear as if they were part of the Matroid struct
    #[serde(flatten)]
    variant_specific_fields: YourEnumOfMatroids
}
1 Like

What you are looking for is called an "associated type". You can google that term for more details.

2 Likes

Thanks! This seems like a good way to solve my problem!

Ty for the reply! I looked up associated types in the rust book. As I understand it, associated types serve as placeholders in trait method definitions. It isn't really clear to me how I could use this to solve my problem?

Associated types have nothing to do with methods. They are type-level functions that can be used to transform one type to another or express a dependency between types. It looks to me like you want:

trait MatroidRepr {
    type Element;
    type Independence;
}

struct GraphicMatroidRepr;

impl MatroidRepr for GraphicMatroidRepr {
    type Element = GraphicMatroidElement;
    type Independence = GraphicMatroidIndependence;
}

struct Matroid<T: MatroidRepr> {
    elements: Vec<T::Element>,
    independence: T::Independence,
}

// Matroid<GraphicalMatroidRepr> has the correct field types

No methods in sight.

6 Likes

Oh wow, that is really clean! Thx so much for your help! :slight_smile: