为切片/?Sized类型实现Deref trait的方案求助
问题解决方法
错误原因
编译失败的核心是ptr::cast::<U>()方法要求目标类型U必须是Sized,而你将T的约束改为?Sized后,无法直接用cast转换到*const T(因为T可能是动态大小类型,比如切片)。
解决方案
我们需要针对普通Sized类型和**动态大小类型(如切片)**分别实现Deref和DerefMut,因为动态大小类型需要特殊的指针构造逻辑。
1. 保留Sized类型的实现
对于固定大小的类型,继续使用原有的指针转换逻辑:
impl<'a, const N: usize, T: Sized> Deref for TypedLinkedListArrayWrapper<'a, N, T> { type Target = T; fn deref(&self) -> &Self::Target { unsafe { &*(self.wrapper.deref().as_ptr() as *const T) } } } impl<'a, const N: usize, T: Sized> DerefMut for TypedLinkedListArrayWrapper<'a, N, T> { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self.wrapper.deref_mut().as_ptr() as *mut T) } } }
2. 为切片类型实现Deref/DerefMut
针对切片[T],需要用slice_from_raw_parts构造合法的切片指针。注意切片长度的计算要和你的分配器逻辑匹配(下面示例假设wrapper.size是切片的元素个数;如果是字节总数,需要除以size_of::<T>(),请根据实际情况调整):
impl<'a, const N: usize, T> Deref for TypedLinkedListArrayWrapper<'a, N, [T]> { type Target = [T]; fn deref(&self) -> &Self::Target { let base_ptr = self.wrapper.deref().as_ptr() as *const T; let len = self.wrapper.size; unsafe { std::slice::from_raw_parts(base_ptr, len) } } } impl<'a, const N: usize, T> DerefMut for TypedLinkedListArrayWrapper<'a, N, [T]> { fn deref_mut(&mut self) -> &mut Self::Target { let base_ptr = self.wrapper.deref_mut().as_ptr() as *mut T; let len = self.wrapper.size; unsafe { std::slice::from_raw_parts_mut(base_ptr, len) } } }
3. (可选)支持其他动态大小类型
如果需要支持trait对象这类DST,你需要额外保存并传入对应的元数据(比如vtable指针),这需要修改分配器的逻辑来存储元数据。如果你的场景仅需兼容切片,上述实现已经足够。
关键注意事项
- 动态大小类型(DST)不能直接通过
cast转换指针,必须使用对应类型的指针构造方法。 - 务必确保切片长度计算准确,否则会导致内存越界等未定义行为。
内容的提问来源于stack exchange,提问作者Jonathan Woollett-light
相关产品推荐
相关产品推荐

