3 ms·
FWIW, it is possible to make it a bit more ergonomic: pub struct SmartRef<'a> { container: &'a Container, widget: usize, } impl <'a> std::ops::De
by idubrov 8y ago
FWIW, it is possible to make it a bit more ergonomic:
pub struct SmartRef<'a> {
container: &'a Container,
widget: usize,
}
impl <'a> std::ops::Deref for SmartRef<'a> {
type Target = Widget; // Widget provides non-traversing functionality
fn deref(&self) -> &Widget {
&self.container.widgets[self.widget]
}
}
impl <'a> SmartRef<'a> {
fn children(&'a self) -> impl Iterator<Item = SmartRef<'a>> {
self.container
.widgets[self.widget]
.children.iter().map(move |w| SmartRef { container: self.container, widget: *w })
}
}
fn boo(container: &Container) {
let root = SmartRef { container, widget: 0 };
println!("name: {}", root.name);
for child in root.children() {
println!("child name: {}", child.name);
}
}
(removed GAT remark -- it does not apply here; was thinking about generalizing this with traits)
- comex 8y agoHmm… that would work, but at the cost of requiring the data to be immutable or use interior mutability. It also removes the size advantage of storing indices over pointers, unless you only make SmartRefs temporarily rather than storing them in your data structures.
- idubrov 8y agoYes, the idea is that you only create them temporarily. Mutability is also possible to some extent with these "smart" pointers. It gets a bit trickier and less ergonomic, though. See https://play.rust-lang.org/?gist=fbf1c24397e7020c95774bf09060b6fd&version=stable&mode=debug&edition=2015 https://play.rust-lang.org/?gist=fbf1c24397e7020c95774bf0906... Another option would be to store something like "Rc<RefCell<Container>>" instead of "&'a mut Container", in which case you will be able to achieve something that behaves like multiple mutable references (with all the concurrency issues of them).