I'm working on MappedRc
which can map Rc
's value to another value without extra allocating and elimates the generic type of Rc
.
Rc<T> + (fn(&T) -> U) ========> MappedRc<U>
This is my implementation:
It works fine except de-referencing needs type checking, where I commented in the playground. Is there a way to avoid this? Thanks.
EDIT: Is there a better way to achieve this without using Any
?
jofas
May 13, 2024, 11:08am
2
If you can use nightly, there is downcast_ref_unchecked
you could use, which is basically this line of code
Thanks for reply, but that needs unsafe Rust.
I don't think there's a way to unerase a type while avoiding both unsafe
and Any
.
In this case, you can avoid the need to unerase the source type U
by moving where the type erasure happens— Package up both the Rc
and the map function into a single type with a U
parameter, and then implement a trait that doesn’t mention U
on that combined type. This can then be type-erased to just the trait interface, making U
disappear:
NB: I renamed U
to S
(for “source”) here.
struct MappedRcImpl<S: ?Sized, F> {
src: Rc<S>,
map_fn: F,
}
impl<S: ?Sized, T: ?Sized, F: Fn(&S) -> &T> AsRef<T> for MappedRcImpl<S, F> {
fn as_ref(&self) -> &T {
(self.map_fn)(&self.src)
}
}
pub struct MappedRc<'a, T: 'a + ?Sized>(Box<dyn 'a + AsRef<T>>);
impl<'a, T: 'a + ?Sized> MappedRc<'a, T> {
pub fn new<S, F>(src: Rc<S>, map_fn: F) -> Self
where
S: ?Sized + 'a,
F: Fn(&S) -> &T + 'a,
{
MappedRc(Box::new(MappedRcImpl { src, map_fn }))
}
}
impl<T: ?Sized> Deref for MappedRc<'_, T> {
type Target = T;
fn deref(&self) -> &T {
<_ as AsRef<T>>::as_ref(&*self.0)
}
}
Fancyflame:
without extra allocating
That works, but caused extra allocation here.
MappedRc ( Box::new( MappedRcImpl { src, map_fn } ) )
The allocation occurred because MappedRcImpl
at least contains a Rc
, which is not zero-sized. Thank you anyway.
system
Closed
August 12, 2024, 5:48am
8
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.