Vector with generic types (heterogeneous container)

Hello,
I need to create a structure (Vector, HashMap etc.) that will hold different types - u8 ... u64, bool.
How to do it?

/// My generic type. T : u8, u16, u32, u64, bool
struct GenericVar<T>
{
    value : T
}

fn main()
{
    let mut list = Vec::new();
    
    let var_u16 = GenericVar::<u16>{ value : u16::default() };
    list.push(var_u16);
    
    let var_u8 = GenericVar::<u8>{ value : u8::default() };
    list.push(var_u8);
}

Rust Playground

I found this but it not compile:

use std::any::Any;

fn main() {
    let mut x = Vec::<Box<Any>>::new();
    x.push(box 1i);
    x.push(box 1.0f32);
    x.push(box vec!["hi", "ho"]);
}

Example Playground
Reddit

Rust vectors can only store one type of item. There’s two ways to deal with this:

  • You can define an enum that has a variant for each type you want to store, or
  • You can use dynamic dispatch to treat several types that implement a trait as a single type:

#[derive(Debug)]
enum GenericVar
{
    Byte(u8),
    Short(u16),
    Int(u32),
    Long(u64),
    Bool(bool)
}


fn main()
{
    let mut enum_list = Vec::new();
    
    let var_u16 = GenericVar::Short( 0u16 ) ;
    enum_list.push(var_u16);
    
    let var_bool = GenericVar::Bool( true ) ;
    enum_list.push(var_bool);

    println!("{:?}", enum_list);

    // or

    use std::fmt::Debug;
    let mut dyn_list: Vec<Box<dyn Debug>> = vec![];

    dyn_list.push(Box::new( 0u16 ));
    dyn_list.push(Box::new( "hello" ));

    println!("{:?}", dyn_list);
}

(Playground)

4 Likes

@2e71828 Thx.

use std::fmt::Debug;

/// My generic type. T : u8, u16, u32, u64, bool
#[derive(Debug)]
struct GenericVar<T>
{
    value : T
}

fn main()
{
    let mut dyn_list: Vec<Box<dyn Debug>> = vec![];

    let var_u16 = GenericVar::<u16>{ value : u16::default() };
    let var_u8 = GenericVar::<u8>{ value : u8::default() };

    dyn_list.push(Box::new( var_u8 ));
    dyn_list.push(Box::new( var_u16 ));

    dyn_list.push(Box::new( "hello" ));

    println!("{:?}", dyn_list);
}

Playground

Under certain circumstances a mixture of enum and trait objects can be practical.

use std::fmt::Debug;

#[derive(Debug)]
enum Object {
    Bool(bool),
    U8(u8),
    U32(u32),
    Ref(Box<dyn Debug>)
}

fn main() {
    let a = [
        Object::Bool(true),
        Object::U32(0),
        Object::Ref(Box::new([1,2,3,4])),
        Object::Ref(
            Box::new([Object::U8(0), Object::U32(1)])
        )
    ];
    println!("{:?}",a);
}
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.