Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- trait Trait {}
- struct Thing {}
- impl Trait for Thing {}
- struct Item {}
- impl Trait for Item {}
- use std::marker::PhantomData;
- // Wrapper around reference with lifetime attached by adding PhantomData
- // Storing just an address is bad, this wrapper should not outlive
- // original reference
- // Implement Eq and Hash to be able to use it in HashSets/HashMaps
- #[derive(PartialEq, Eq, Hash)]
- struct HashEqPtr<'a>(usize, PhantomData<&'a ()>);
- impl<'a> HashEqPtr<'a> {
- // Accept Ts which don't have known compile time size.
- fn new<T: ?Sized>(t: &'a T) -> Self {
- // Cast to raw pointer, cast to thin pointer, then to address
- let fat_ptr = t as *const T;
- let thin_ptr = fat_ptr as *const ();
- let addr = thin_ptr as usize;
- println!("new: {:p} fat: {:p} thin: {:p} addr: {:x}", t, fat_ptr, thin_ptr, addr);
- HashEqPtr(addr, PhantomData)
- }
- }
- fn main() {
- let t = Thing {};
- let i = Item {};
- println!("&t: {:p}", &t);
- println!("&i: {:p}", &i);
- let xs: Vec<&Trait> = vec![&t, &i];
- println!("xs[0]: {:p}", xs[0]);
- println!("xs[1]: {:p}", xs[1]);
- use std::collections::HashSet;
- let mut hm: HashSet<HashEqPtr> = HashSet::new();
- for x in &xs {
- println!("x: {:p}", x);
- hm.insert(HashEqPtr::new(x));
- }
- assert_eq!(hm.len(), 2);
- for x in &xs {
- println!("x: {:p}", x);
- assert_eq!(hm.contains(&HashEqPtr::new(x)), true);
- }
- // WHAT??
- //assert_eq!(hm.contains(&HashEqPtr::new(&t)), true);
- //assert_eq!(hm.contains(&HashEqPtr::new(&i)), true);
- let t2 = Thing {};
- assert_eq!(hm.contains(&HashEqPtr::new(&t2)), false);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement