0

I am aware of options of trait objects and enum to store different types of objects in a collection, but in both cases, there is a penalty on the runtime efficiency (if I understand it well). In the trait's case, there must be a dynamic dispatch (dyn) and in the enum, all possibilities are checked at runtime (just like a switch). Right? There is a loss of efficiency in both cases, so I was wondering if there is any right way of doing it without that loss.

Using the example in Listing 17-9, for instance:

let screen = Screen {
        components: vec![
            Box::new(SelectBox {
                width: 75,
                height: 10,
                options: vec![
                    String::from("Yes"),
                    String::from("Maybe"),
                    String::from("No"),
                ],
            }),
            Box::new(Button {
                width: 50,
                height: 10,
                label: String::from("OK"),
            }),
        ],
    };

In this case, at compile-time, I know that the vector has those instances, so I don't understand the need for that loss.

How is that different from having a vector of strings? They may also have different sizes.

  • 1
    Note that, if the compiler provably knows the type of a trait object, it might be able to _devirtualize_ the call and optimize it as if it was a normal function call: See the discussion here: https://stackoverflow.com/questions/28621980/what-are-the-actual-runtime-performance-costs-of-dynamic-dispatch – cadolphs Jun 22 '21 at 17:32
  • 3
    A compile-time heterogeneous collection of elements with different types would be a tuple: `(SelectBox, Button)`. – kmdreko Jun 22 '21 at 18:47
  • 1
    All `String` instances have the same size. They may have different _lengths_ but the size of the `String` struct as stored in the vector is the same. – Jmb Jun 23 '21 at 07:57

1 Answers1

3

Rust doesn't have a general built-in mechanism for doing this with Vecs at compile time, simply because in some (most?) scenarios the types of every object in the Vec is not determinable at compile time. However, it's possible in certain scenarios that the optimizer may be able to figure out that the types are known at compile time and devirtualize the function calls, but you'd have to analyze your compiled code to know if the optimizer was able to do it for your particular case.

It is worth noting that the concern about the inefficiency here possibly may be overblown. While both these methods have some overhead, it's likely this will not be the slowest part of your code's execution (unless you have profiled your code and know otherwise).

effect
  • 1,279
  • 6
  • 13