The main thing you need is some way to get the value from the array without moving it. Two such solutions:
Use mem::replace and mem::uninitialized to replace every value in the array with garbage, returning the original:
let one = unsafe { mem::replace(&mut v[0], mem::uninitialized()) }; bar(one);
Use ptr::read to leave the value in the array, but return it back:
let two = unsafe { ptr::read(&v[0]) }; bar(two);
It is just a question of one of them several times in the cycle, and you are good to go.
There is only one tiny problem: do you see those unsafe ? You guessed it; this is completely, horribly violated in the broader case:
- We leave this array full of arbitrary bits, which will still be treated as
Foo . In the case of this, nothing special happens when this array goes out of scope, since there is no special Drop implementation for the Foo type, but if that were the case, it would be access to invalid memory. Bad news! - If panic occurs in the middle of moving values ββ(for example, somewhere inside the
bar function), the array will be in a partially uninitialized state. This is another (subtle) way in which the Drop implementation can be implemented, so now we need to know which values ββstill belong to the array and which were deleted. We are responsible for releasing the values ββthat we still own, and not others. - Nothing prevents us from accidentally accessing newly invalid values ββin the array.
The correct solution is to keep track of how many of the values ββin the array are valid / invalid. When the array is discarded, you can leave the remaining valid elements and ignore the invalid ones. It would also be very nice if we could do this job for arrays of different sizes ...
Where is arrayvec located. It does not have an exact implementation (because it is smarter), but it does have the same semantics:
extern crate arrayvec; use arrayvec::ArrayVec; #[derive(Debug)] struct Foo; fn bar(foo: Foo) { println!("{:?}", foo) } fn main() { let v = ArrayVec::from([Foo, Foo, Foo]); for f in v { bar(f); } }
source share