0

How can I define a vector of comparable in Rust?

Say, i32, i16...

I tried arr: Vec<Ord> but the compiler complains about the trait "std::cmp::Ord" cannot be made into an object

Basically I need to store a vector of a vector of comparable objects. e.g.

    struct Setup<T: Ord + Copy> {
        arr: Vec<Vec<T>>
    }

    impl<T: Ord + Copy> Setup<T> {
        fn new() -> Self {
            Self {
                arr: vec![
                    vec![1, 2, 3, 4, 5],
                    vec![1.0, 2.0, 3.0]
                ]
            }
        }
    }

Instead of letting the consumer decide what exactly the type is, I would like they can get a vector of comparable stuffs.

user3003238
  • 1,517
  • 10
  • 17
  • It would be much easier to provide an explicit answer if you included a more complete example of your code. – loganfsmyth Mar 10 '19 at 05:30
  • 1
    I wonder if expanding on the problem you're trying to solve, rather than one specific possibility for a solution, might help you get a better answer. Why are these 2D vectors? Why do they need different types? What is the usecase for this structure and what motivates it? – loganfsmyth Mar 10 '19 at 07:20
  • Possible duplicate of [Vector of objects belonging to a trait](https://stackoverflow.com/questions/25818082/vector-of-objects-belonging-to-a-trait) – E_net4 Mar 10 '19 at 12:56

1 Answers1

1

The type Vec<Ord> would be a Vec where each item is a trait object. What you'd want to do is do Vec<T> and then set the trait bound on T to be : Ord, e.g.

struct Foo<T: Ord> {
  arr: Vec<T>,
}
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • Thanks for the answer. That's my initial thought, but is there a way to create an instance for that? Actually what I need is `Vec>` and need to store an array of `i32` and an array of `i16`. Do you know how can I implement the `new` for this case? Instead of letting the consumers declare what exactly the type they need, I would like they get something can be comparable within the vector only. – user3003238 Mar 10 '19 at 05:38
  • That would not store enough type information. A type implementing `Ord` can only be compared be compared with another value of the same type, and a trait object of `Ord` would have no way of knowing what type it was allowed to be compared to. – loganfsmyth Mar 10 '19 at 06:34
  • You can have a `Vec` of a single type, like `i32`, but you can't have a `Vec` or arbitrary integer types that are mixed and expect to be able to compare them. – loganfsmyth Mar 10 '19 at 06:40
  • 1
    @user3003238 There is other solution like use an enum if you want mix two type. – Stargateur Mar 10 '19 at 07:15
  • Yup, the main thing is that _something_ needs to decide what types are what somewhere. – loganfsmyth Mar 10 '19 at 07:19
  • 1
    @user3003238 *hmm, that's sad* It sounds strange at first, but it's not an arbitrary limitation, it follows from the fact that Rust's vector really provides efficient contiguous storage for its values without introducing indirection. (The very same thing applies to a C++ `std::vector`.) But if you need indirection, it's easy to get it! Simply store make your vector a `Vec>`. Or create your own `ComparableNumber` trait that extends `Ord`, and also provides a way to retrieve the number, and make the vector a `Vec>`. – user4815162342 Mar 10 '19 at 10:26