2

I have a trait, MyTrait, that defines a method called my_func that returns an array of unknown size. The reason for this is that the size of the array returned from this method will depend on the struct that implements the trait. So, the method definition looks like this:

MyTrait<T: Clone + Float> {
    fn my_func() -> &[&[T]];
}

Now, I'm trying to implement this trait with the following method:

impl MyStruct {
    const matrix_desc: [[u32; 4]; 4] = [
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 1]
    ];
}

impl MyTrait<u32> for MyStruct {
    fn my_func() -> &[&[u32]] {
        &matrix_desc
    }
}

However, I keep getting errors saying there's a type-mismatch and that Rust expected a &[&[u32]] but got a &[[u32; 4]; 4]. This is very clear to me but I'm not sure how to fix it. I've also tried using the Sized trait but I can't seem to get that to work. Does anyone know how I can return arrays of an unknown size at compile time?

Also, for bonus points, does anyone know how I can force this 2d-array to be square?

5
  • 3
    This seems like a situation where Vec would help. Is there a reason why you can't return a Vec<Vec<T>> ? Commented Jun 11, 2019 at 7:15
  • @Sunreef, what makes vector so much better that it's worth for a 4x4 matrix? Commented Jun 11, 2019 at 9:26
  • 2
    @JanHudec If it's always a 4x4 matrix, then you can use [[T;4];4]. But he said he wants unknown sizes. That's what Vec does. Commented Jun 11, 2019 at 9:28
  • @Sunreef, you can do unknown sizes with plain references just fine. The thing that Vec adds is ownership. If it's not needed, it shouldn't be there. Commented Jun 11, 2019 at 9:39
  • @Sunreef The actual size of the matrix doesn't change when the trait is implemented, I just don't know what the size is with respect to the trait definition. I could have a second struct called StructB that implements a [[T;8];8] for example. I do not want the matrix size to change when implemented but I can't determine what the size is in the trait definition Commented Jun 12, 2019 at 0:45

2 Answers 2

4

A known-length array is a value that is included directly in the containing object. So a [[u32; 4]; 4] is a block of memory with 16 u32s. You can convert it to a &[[u32;4]], which is a pointer and number of rows, but &[&[u32]] wants to point to an array of pointer-size pairs and that does not exist in the original value.

Like in C, nested arrays are not particularly nice to work with. I would probably go the route of flattening it to [u32; 4 * 4] and &[u32] and possibly wrap it with something defining std::ops::Index<(usize, usize)>. That immediately forces the matrix to be rectangular (a &[&[u32]] can have each row of different length) and you could further check that it is actually square in the index method (and any other methods you define for the algebra).

Or just try to find an already written matrix library on crates.io—I'm quite sure there will be some.

Sign up to request clarification or add additional context in comments.

1 Comment

For small matrices like 4x4, 3x3 and small vectors, nalgebra is a very nice crate.
1

If it's ok to declare matrix_desc as slice this should work:

struct MyStruct;

impl MyStruct {
    const matrix_desc: &'static [&'static [u32]] = &[
        &[1, 0, 0, 0],
        &[0, 1, 0, 0],
        &[0, 0, 1, 0],
        &[0, 0, 0, 1]
    ];
}

trait MyTrait<T> {
    fn my_func() -> &'static [&'static [T]];
}

impl MyTrait<u32> for MyStruct {
    fn my_func() -> &'static [&'static [u32]] {
        &Self::matrix_desc
    }
}

It seems that fixed & generic sized arrays are not very well supported at the moment. For example, this doesn't work:

trait MyTrait<T> {
    const SIZE: usize;
    fn my_func() -> [[T; SIZE]; SIZE];
}

1 Comment

I tried this as well and this might be the route I end up going in

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.