Description
This enhancement suggestion looks a bit silly to me, but I think it's worth asking for an opinion in this bug tracker.
I think this is a reasonable usage pattern of Vec::spare_capacity_mut
and Vec::set_len
. I've used it with a larger SomeData to avoid both an useless initialization and the use of Vec::push
that in those cases is slightly slower, the disadvantage is that this code contains unsafe{}
and it's a bit fiddly:
#![feature(vec_spare_capacity, maybe_uninit_extra)]
fn cond(i: usize) -> bool { i % 2 == 0 }
struct SomeData(usize); // Something larger.
fn main() {
const N: usize = 1_000_000;
let mut data = Vec::with_capacity(N);
let mut data_len = 0;
let data_uninit = data.spare_capacity_mut();
for i in 0 .. N {
if cond(i) {
data_uninit[data_len].write(SomeData(i));
data_len += 1;
}
}
unsafe {
data.set_len(data_len);
}
}
An API that removes the unsafety could be:
#![feature(vec_push_in_capacity)]
fn cond(i: usize) -> bool { i % 2 == 0 }
struct SomeData(usize); // Something larger.
fn main() {
const N: usize = 1_000_000;
let mut data = Vec::with_capacity(N);
for i in 0 .. N {
if cond(i) {
data.push_in_capacity(SomeData(i));
}
}
}
Vec::push_in_capacity
is similar to Vec::push
, but it doesn't include any growing strategy (and doesn't include such growing/realloc code in the binary), so it just uses the capacity. If the capacity isn't enough it panics (just like the first code panics if the capacity is finished at data_uninit[data_len]
).