Как сделать границу черты, которая требует массив фиксированного размера? - PullRequest
0 голосов
/ 11 июня 2019

Я пытаюсь создать черту, которая является только композицией других черт, с конечной целью создания черты, которая доказывает, что тип является массивом размеров.

Кроме того, я хотел бы иметь возможность делать это в стабильном Rust без дополнительных библиотек.

Я пытался добавить несколько границ признаков, чтобы имитировать ограничения массива фиксированного размера, например:

trait SizedArray<T>
where
    T: Sized + Eq + Copy + Clone,
{
}

impl<T> SizedArray<T> for [T; 32] where T: Sized + Eq + Copy + Clone {}

fn processArray<T, U>(array: T)
where
    T: SizedArray<U>,
    U: Sized + Eq + Copy + Clone,
{
    let a = array[0];
    for i in array.iter() {
        let size = array.len();
        /* do something with the array */
    }
}

fn main() {
    let array = [0u8; 32];

    processArray(array);
}

Но когда я делаю это и пытаюсь использовать фиксированныйразмерный массив, такой как [u8; 32]:

Я получаю:

Compiling playground v0.0.1 (/playground)
error[E0608]: cannot index into a value of type `T`
  --> src/main.rs:12:13
   |
12 |     let a = array[0];
   |             ^^^^^^^^

error[E0599]: no method named `iter` found for type `T` in the current scope
  --> src/main.rs:13:20
   |
13 |     for i in array.iter() {
   |                    ^^^^

error[E0599]: no method named `len` found for type `T` in the current scope
  --> src/main.rs:14:26
   |
14 |         let size = array.len();
   |                          ^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `len`, perhaps you need to implement it:
           candidate #1: `std::iter::ExactSizeIterator`

Тип [u8; 32] явно имеет все эти методы, но я не знаю, как сказать Rustищите их.

Детская площадка

1 Ответ

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

Const дженерики (ночные)

В будущем вы можете использовать const generics, чтобы выразить это напрямую:

#![feature(const_generics)]

fn process_array<T, const N: usize>(array: [T; N])
where
    T: Sized + Eq + Copy + Clone,
{
    let a = array[0];
    for i in array.iter() {
        let size = array.len();
        /* do something with the array */
    }
}

fn main() {
    let array = [0u8; 32];

    process_array(array);
}

Смотри также:

AsRef (стабильный)

Я бы, вероятно, просто использовал AsRef<[T]> в стабильном Rust; Для всех функций, которые вы вызываете (iter, len, index), вы все равно уже делегируете срезу:

fn process_array<T>(array: impl AsRef<[T]>)
where
    T: Sized + Eq + Copy + Clone,
{
    let array = array.as_ref();
    let _a = array[0];
    for _i in array.iter() {
        let _size = array.len();
        /* do something with the array */
    }
}

fn main() {
    let array = [0u8; 32];

    process_array(array);
}
...