I would like to implement a structure which contains a const array. But using standard array type means array length is a part of the structure type. Thus two structures with arrays having different length have two different types. Using Vec inside such structure looks like overhead because it also contains capacity and allocator which are not needed because array is constant. Basically I would like to have something like (pseudocode):
struct S {
arr: [i32],
}
Are there any standard or non-standard type to represent such constant array?
Is the array value known at compile time? (const constructable). If so, then &'static [i32] might work?
I think the issue is that dynamically sized [i32] doesn't have anywhere to encode the length. I think you'd need some kind of pointer indirection (Box<[i32]> or Rc<[i32]>?)
It's also possible to make your type work with unsize coercion, as long as the array is the last field. That will require you to use some kind of indirection, like Box or &, to store multiple lengths in a common container, though:
struct S<T: ?Sized = [i32]> {
arr: T,
}
impl<const N: usize> std::ops::Deref for S<[i32; N]> {
type Target = S;
fn deref(&self) -> &S {
self
}
}
impl<const N:usize> std::ops::DerefMut for S<[i32;N]> {
fn deref_mut(&mut self)->&mut S {
self
}
}
impl<const N:usize> S<[i32;N]> {
pub fn boxed(self)->Box<S> {
Box::new(self)
}
}
impl S {
// for example...
fn sum(&self) -> i32 {
let mut out = 0;
for &x in self.arr.iter() {
out += x
}
out
}
}
#[test]
fn test_single() {
let s = S { arr: [2, 3, 4] };
assert_eq!(9, s.sum());
}
#[test]
fn test_vec() {
let v = vec![
S{arr: [2,3,4]}.boxed(),
S{arr: [5,4]}.boxed(),
S{arr: [1,1,1,1,1,1,1,1,1]}.boxed(),
];
for s in v {
assert_eq!(9, s.sum());
}
}
Unfortunately parameterizing with length doesn't work because I need arrays of different length to has the same type. Anyway @danjl1100 provided obvious solution.