ibarrond
ibarrond

Reputation: 7641

Iterating a struct holding multiple iterables, both by values and by refererences

Say we have two types:

pub struct MyElement {
   a: Box<int>,
   b: Box<int>,
}

pub struct MySet {
   as: Box<[int]>,
   bs: Box<[int]>,
}

How can I, without cloning/copying, implement:

  1. MySet.into_iter() to yield items of type MyElement?
  2. MySet.iter() to yield items of type &MyElement?

Upvotes: 0

Views: 69

Answers (1)

nanofarad
nanofarad

Reputation: 41281

This isn't possible if we interpret "without cloning/copying" as "without creating new Boxes cloned from the existing ones, or copying ints into new Boxes". If you can copy the integers into new boxes, paying the memory allocation cost, you can easily create MyElement structs for into_iter, but this is neither a full solution nor fits the question's intent.

MySet.into_iter() to yield items of type MyElement?

The necessary individual boxes cannot be created without copying and making new allocations. Given a slice of integers allocated through the global allocator, neither you nor the standard library can turn it into a bunch of individual allocations that can then be separately deallocated - such small allocations neither fit the preconditions of the Rust allocator trait, nor do they work on many real-world memory allocators (e.g. imagine a real-world allocator that allocated a page for a large slice but is now being asked to put small allocations onto free lists that they don't belong on, without the right metadata nearby)

MySet.iter() to yield items of type &MyElement?

Likewise, you need a struct with the layout of two Boxes to reference, you do not have one, and you cannot produce one.

A key finding here is that MyElement tries to do too much to be used this way - it tries to hold individual elements, owning them. Rather, a type with the appropriate lifetime annotations, holding references into the original slices, could be used, depending on the (unstated) other context in the problem.

Upvotes: 0

Related Questions