简体   繁体   中英

How do I make a trait bound that requires a fixed size array?

I'm trying to create a trait that is only a composition of other traits with the end goal of creating a trait that proves the type is a sized array.

Additionally, I would like to be able to do this in stable Rust with no extra libraries.

I've tried adding a bunch of trait bounds to mimic the limitations of a fixed size array, like the following:

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

But when I do so and try to use a fixed sized array, such as [u8; 32] [u8; 32] :

I get:

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`

The type [u8; 32] [u8; 32] clearly has all of those methods, but I don't know how to tell Rust to look for them.

Playground

Const generics (Nightly)

In the future, you can use const generics to express this directly:

#![feature(min_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);
}

See also:

AsRef (stable)

I'd probably just use AsRef<[T]> in stable Rust; For all the functions you call ( iter , len , index ) you are already delegating to a slice anyway:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM