0

I have a struct:

struct A<T> {
    name: String,
    Value: T,
}

let a = A {
    name: String::from("a"),
    value: 1,
};
let b = A {
    name: String::from("b"),
    value: String::from("b"),
};

let v = Vec::new();

How do I put a and b to v? I want Vec<A> to be a function's return type. I think struct A has wrong statement, but I don't know how to fix it. Use Box?

Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
uuz
  • 21
  • 5
  • 2
    `a` and `b` can be treated as diffretent types `A` and `A` for example. They cannot be pushed directly in the vector. You could wrap them in an enum to solve it.... – Netwave May 09 '21 at 16:45
  • Great! Thanks a lot! – uuz May 09 '21 at 16:56

1 Answers1

0

In Rust Generic Types are basically different types. You cannot have a collection of objects which have different generic arguments.

There are two solutions to this problem, depending on your situation.

You know upfront what types are going to be used

If you know what types are going to be used throughout the program, you can create an enum of A<T> with those types:

enum ATypes {
    u32(A<u32>),
    string(A<String>),
}
v.push(ATypes::u32(a));
v.push(ATypes::string(b));

You don't know what types are going to be used

In this case you have to rely on dynamic dispatch. To do this we use Trait objects. First, we have to create a trait for the A's:

trait AnyA {}

Then, we need to implement it for all the A's:

impl<T> AnyA for A<T> {}

Then, Create a Vec of trait objects:

let mut arr: Vec<Box<dyn AnyA>> = Vec::new();

Now, to push something to the Vec do:

arr.push(Box::new(a));
arr.push(Box::new(b)); 

All the methods you want to use on the elements of the Vec have to be implemented on the trait.

Sadly this method is quite limited because of the lack of GATs in Rust

Misty
  • 356
  • 2
  • 8