Is this sensible and/or am I reinventing the wheel?

I just wrote up the following trait:

trait ConstLengthIterator<const N: usize> : Iterator {}

impl<T, const N: usize> ConstLengthIterator<N> for std::array::IntoIter<T, N> {}
impl<T, I, F, const N: usize> ConstLengthIterator<N> for std::iter::Map<I, F> where 
    I : Iterator,
    F : FnMut(<I as Iterator>::Item) -> T {}
impl<I1, I2, const N: usize> ConstLengthIterator<N> for std::iter::Zip<I1, I2> where
    I1 : ConstLengthIterator<N>,
    I2 : ConstLengthIterator<N> {}

Probably could use some additional functions like ways to safely create const length iterators and ways to safely use them to populate arrays, but you get the drift hopefully.

Is this useful? And has it been done, and should I just use a crate someone else has already developed? And if the answer is "yes" to the first question and "no" to the second question, should I create a crate myself and upload it?

The hard part is that the Iterator is a stateful object. Iterator::next() modifies its length but doesn't change its type.

let mut iter = [99_u32; 100].into_const_iter();
let first = iter.next().unwrap();
let arr: [u32; 100] = iter.const_collect(); // what should happen?

I believe the SOTA is to collect into the ArrayVec<T> and treat it as an error case if it's not full.

There is

That solves this by const-genericifying the entire iterator trait.

let res: [_; 2] = [1, 2, 3, 4]
    .into_iter_fixed()
    .zip([4, 3, 2, 1])
    .map(|(a, b)| a + b)
    .skip::<1>()
    .take::<2>()
    .collect();

I think you'll have far more luck with a ConstLengthIntoIterator, since as Hyeonu mentioned the only constant-length iterators are the infinitely-long ones.

I think you'll also end up hitting a bunch of problems on stable right now, since bounds on const generic values are so restricted.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.