Как использовать GenericArray с ограниченным диапазоном длины, который может быть обнаружен во время компиляции? - PullRequest
1 голос
/ 29 мая 2020

Например,

struct Foo<T, N: ArrayLength<T>> {
    data: GenericArray<T, N>
}

Я хочу, чтобы длина массива данных была ограничена диапазоном от 100 до 1024 байтов. Затем, если Foo используется как let f: Foo<u8, generic_array::typenum::U8> = Foo {data: GenericArray::default()};, это вызовет ошибку компиляции.

Ответы [ 2 ]

1 голос
/ 30 мая 2020

Я думаю, что вам нужны Const Generics.

Эта функция существует в Rust, но она все еще находится в стадии разработки. Вы можете использовать его ночью, и, насколько я понимаю, есть некоторые варианты использования, которые работают по назначению.

В основном это позволяет вам иметь общий c тип, например:

struct Foo<T, const N: usize> {
    // Here you can use `N` as a `const`. For example, to define the size of a `std::array`
}

Вот ссылки, по которым можно перейти к этой функции:

  • Общие типы const RF C
  • Проблема отслеживания для этой функции в ржавчине c репо
  • Последний отчет от varkor, основного разработчика этой функции.

Все в общем, мне жаль, что вы пока не можете использовать его в стабильной версии. Но для создания великих вещей нужно время.

Проверьте, можете ли вы его использовать. Есть несколько типов std, которые действительно используют его сегодня (и в стабильном состоянии, потому что они уже прошли аудит на предмет надежности и стабильности). Например, std::array широко использует его как минимум 1 год go.

Надеюсь, это поможет <3 </p>

1 голос
/ 30 мая 2020

Я немного поигрался с typenum, это работает:

use generic_array::{ArrayLength, GenericArray};
use typenum::{IsGreaterOrEqual, IsLessOrEqual, Same, B1, U100, U1024, U99};

struct Foo<T, N>
where
    N: ArrayLength<T>,
    N: IsGreaterOrEqual<U100, Output = True>,
    N: IsLessOrEqual<U1024, Output = True>,
{
    data: GenericArray<T, N>,
}

fn main() {
    let f: Foo<u8, U100> = Foo {
        data: GenericArray::default(),
    };
    // Does not compile
    let f: Foo<u8, U99> = Foo {
        data: GenericArray::default(),
    };
}

The IsGreaterOrEqual<M> et c. черты, что сбивает с толку, реализованы, даже когда N < M. Вы должны получить их результат, посмотрев на соответствующий тип Output. Если это B1 или его синоним True, тогда N действительно больше или равно M.

Вы можете попытаться написать черту, связанную как <N as IsGreaterOrEqual<U100>>::Output == B1, но это не возможно. Вы можете ограничить связанный тип, как в примере кода, или с помощью вспомогательного признака в typenum, Same: <N as IsGreaterOrEqual<U100>>::Output: Same<B1>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...