1

I'm trying to define a custom structure with a field that can be a std::vec::Vec with any type of element:

use std::vec::Vec;

#[derive(Debug, PartialEq)]
pub struct BertDictionary {
    data: Vec<(Any, Any)>  // not work also with Vec<(_, _)>
}

When compiling, this generates a E0308 error which means the compiler is unable to infer the concrete type. Is is possible to define such a structure?

As an example, I'm going to use this vector when each element may be represented like (name, "user"), (id, 1) and so on.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Relrin
  • 760
  • 2
  • 10
  • 28
  • 3
    Are you aware of `AnyMap`? And be aware that getting the value out of `Any` requires knowing its concrete type. – Matthieu M. Aug 02 '16 at 09:21
  • @MatthieuM. Sure, I know about that Any require implementing trait for your types, but doesn't know something about AnyMap. Maybe it's a good fit, however I wonder if can I write this constructions which described in this topic – Relrin Aug 02 '16 at 09:34
  • 2
    [`AnyMap`](https://github.com/chris-morgan/anymap) is written by Chris Morgan and [`rust-typemap`](https://github.com/reem/rust-typemap) is written by Jonathan Reem, if you are interested in investigating them. – Matthieu M. Aug 02 '16 at 10:32
  • Thanks you for the useful answer! – Relrin Aug 02 '16 at 10:51
  • 1
    Possible duplicate of [Vector of objects belonging to a trait](http://stackoverflow.com/questions/25818082/vector-of-objects-belonging-to-a-trait) – Francis Gagné Aug 03 '16 at 01:37

1 Answers1

3

Any is a trait, not a concrete type, so you need to add a generic type parameter to the struct.

struct BertDirectory<T: Any> {
    data: Vec<T>
}

You might also want to ensure that T is also something that implements Debug and PartialEq. This isn't required to compile, but would be if you want to ensure that BertDirectory always implements those traits. Otherwise, it will only implement Debug when T does so.

struct BertDirectory<T: Any + Debug + PartialEq> {
    data: Vec<T>
}

Even given both of those things I don't know that this will give you what you really want because data will still be constrained to hold a single type. T can only ever represent a single type per instance of the struct.

If you need data to store values of different types, you might instead want to look into using trait objects instead, which is Rust's way of using vTables:

pub trait MyTrait: Debug {
    // you can still use Any by doing MyTrait: Any + Debug
    // Note that you won't be able to derive PartialEq for your trait 
    // because PartialEq can't be made into a TraitObject

    // can also define whatever methods you would want on your data, which
    // might be preferable to using Any, if possible
}

pub struct BertDirectory<T: MyTrait>{
    data: Vec<(Box<MyTrait>, Box<MyTrait>)>
}

That way the concrete type of T would not need to be known at compile time. Each element in data could be of a different concrete type and the correct methods would be called automatically. You would not be able to derive PartialEq, though, so you'd just have to implement that yourself.

allTwentyQuestions
  • 1,160
  • 7
  • 11