Basically wrap your data struct in Option<Rc<RefCell<_>>>
Better yet, use your custom type that provides few helper functions that make using it as nice as old C++ pointers.
Obviously there's no pointer arithmetic, but it works great for dynamically allocated structures like trees or linked lists.
Please comment how it's a horrible idea that will bring doom to me and my family.
fn main() {
struct Data { pub number: i32 } // struct Data { int number; };
let mut p:Pointer<Data> = Pointer(None); // Data *p = NULL;
println!("{}", p.is_none()); // printf(p == NULL ? "true\n" : "false\n");
p = Pointer::new(Data { number: 5 }); // p = new Data { number: 5 };
println!("{}", p.pointed().number); // printf("%d\n", p->number);
let q = p.clone(); // auto q = p;
q.pointed().number = 6; // q->number = 6;
println!("{}", p.pointed().number); // printf("%d\n", p->number);
println!("{}", p.is_clone_of(&q)); // printf(p == q ? "true\n" : "false\n");
} // delete p;
Helper Pointer<T> type:
use std::{rc::Rc, cell::{RefCell, RefMut}};
#[derive(Debug)]
struct Pointer<T>(Option<Rc<RefCell<T>>>);
impl<T> Clone for Pointer<T> {
fn clone(&self) -> Self {
Pointer(Some(self.0.as_ref().unwrap().clone()))
}
}
impl<T> Pointer<T> {
pub fn new(d: T) -> Pointer<T> {
Pointer(Some(Rc::new(RefCell::new(d))))
}
pub fn pointed(&self) -> RefMut<T> {
let res = self.0.as_ref().unwrap().as_ref().borrow_mut();
res
}
pub fn is_clone_of(&self, other:&Pointer<T>) -> bool {
Rc::ptr_eq(&self.0.as_ref().unwrap(), &other.0.as_ref().unwrap())
}
pub fn is_none(&self) -> bool {
self.0.is_none()
}
}
Live version (Rust):
https://play.rust-lang.org/?gist=f43ce73b89537e0a9ae0586169b...
Live version (C++):
http://tpcg.io/_LNG59M
Rust has pointers. If you want to program like old school C++, wrap everything in unsafe and use all the pointers you want.