Возвращение многомерного массива неизвестного размера из функции в Rust - PullRequest
0 голосов
/ 11 июня 2019

У меня есть черта MyTrait, которая определяет метод с именем my_func, который возвращает массив неизвестного размера. Причина этого заключается в том, что размер массива, возвращаемого этим методом, будет зависеть от структуры, которая реализует черту. Итак, определение метода выглядит так:

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

Теперь я пытаюсь реализовать эту черту следующим способом:

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
    }
}

Однако я продолжаю получать сообщения о том, что есть несоответствие типов и что Rust ожидал &[&[u32]], но получил &[[u32; 4]; 4]. Это очень ясно для меня, но я не уверен, как это исправить. Я также пытался использовать черту Sized, но не могу заставить ее работать. Кто-нибудь знает, как я могу вернуть массивы неизвестного размера во время компиляции?

Кроме того, кто-нибудь знает о бонусных баллах, как заставить этот 2d-массив быть квадратным?

Ответы [ 2 ]

2 голосов
/ 11 июня 2019

Массив известной длины - это значение, которое включается непосредственно в содержащий объект.Таким образом, [[u32; 4]; 4] - это блок памяти с 16 u32 с.Вы можете преобразовать его в &[[u32;4]], который является указателем и числом строк, но &[&[u32]] хочет указать на массив пар размера указателя и который не существует в исходном значении.

Как и в С, вложенные массивы не особенно хороши для работы.Я бы, вероятно, пошел бы путем выравнивания этого к [u32; 4 * 4] и &[u32] и возможно обернул бы это чем-то определяющим std::ops::Index<(usize, usize)>.Это немедленно приводит к тому, что матрица становится прямоугольной (a &[&[u32]] может иметь каждую строку разной длины), и вы можете дополнительно проверить, что она на самом деле является квадратной в методе индекса (и любых других методах, которые вы определяете для алгебры).

Или просто попробуйте найти уже написанную матричную библиотеку на crates.io - я уверен, что она будет.

1 голос
/ 11 июня 2019

Если можно объявить matrix_desc как срез, это должно работать:

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
    }
}

Кажется, что массивы фиксированного и универсального размера в настоящее время не очень хорошо поддерживаются. Например, это не работает:

trait MyTrait<T> {
    const SIZE: usize;
    fn my_func() -> [[T; SIZE]; SIZE];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...