I've come to realize that if I want to accomplish grouping of semi-homogenous items in a space-efficient, stack-allocated, 'array-like', yet fixed-layout form (i.e. not [Box<dyn CommonTraits>; N] or [EnumWithCommonTraits; N]), one solution is to write custom tuple structs for each anticipated number of items:
pub struct ThreeItems<T1, T2, T3> (T1, T2, T3)
where
T1: CommonTraits,
T2: CommonTraits,
T3: CommonTraits;
For which it's straightforward to implement the things I'd like to see a collection do such as iterators or indexing. I was especially happy to find that Iterator<Item = &'a dyn mut CommonTraits> works, giving the magic of dyn Trait without requiring a Box, woohoo!
But I just don't want to deal with the whole copy/paste/rename/add process any more than I have to, especially since I've got a few use cases for this concept... so macros! The biggest problem (I think) comes in incrementing the generic types T1/T2/T3/T4/etc. as I'm pretty sure I've run across the issue of being unable to concatenate 'T' with an int to create a valid token within a macro before. Though calling make_tuple_struct!(SixItems; T1, T2, T3, T4, T5, T6) etc. would still be a heck of a lot better.
Does anyone have any thoughts or good references where something similar may have already been done? Also, I worry there may come issues with trying to actually generate and use a container for N known items at runtime. But I'm hopeful that the number and series of types it contains can be hidden behind an impl ContainerTrait, or else only create/use/drop the struct within the context of a single run function scope so the cluster of generics never needs to be seen.
The thing that's really nagging at me with this is that any permutation of T1/T2/.../T42 has a fixed number of items, max alignment, and (taking into account alignments) a total required size. A tuple struct with generics lets the compiler work out all the details, but with evaluatable const generics it seems this may be possible in a more generic sense.
There is an alternate solution, which doesn't won't work very well for most of my use cases, using const generics to make arrays for all possible types that implement some CommonTraits:
pub struct DenseGroup<const N1: usize, const N2: usize> {
type1s: [Struct1; N1],
type2s: [Struct2; N2],
// for all possible structs that implement the desired common traits.
}
This would end up way too complex for several of my cases, particularly where each struct has its own generics which strongly change its size, for which I'd have to make separate arrays for every combination of generics for every struct, yikes!