为一种特定的泛型类型专门化方法
Specialize method for one specific generic type
我正在为 C 库编写包装器,但我一直在编写大量类型,例如 CVecOf<anything>
:
#[repr(C)]
pub struct CVecOfPoint {
pub array: *mut Point2i,
pub size: usize,
}
impl CVecOfPoint {
pub fn rustify(&self) -> Vec<Point2i> {
(0..self.size)
.map(|i| unsafe { *(self.array.offset(i as isize)) })
.collect::<Vec<_>>()
}
}
#[repr(C)]
pub struct CVecOfPoints {
pub array: *mut CVecOfPoint,
pub size: usize,
}
impl CVecOfPoints {
pub fn rustify(&self) -> Vec<Vec<Point2i>> {
(0..self.size)
.map(|i| unsafe {
let vec = &*self.array.offset(i as isize);
vec.rustify()
})
.collect::<Vec<_>>()
}
}
pub struct CVecOfPointsOfPoints;
pub struct CVecOfPointsOfPointsOfPoints;
pub struct CVecOfPointsOfPointsOfPointsOfPoints;
我只想用以下映射规则编写 CVec<T>
:
rustify :=
T -> T
CVec<T> -> Vec<T>
因此 CVecOfPointsOfPointsOfPointsOfPoints
就是 CVec<CVec<CVec<CVec<Cvec<Point>>>>>
。
感谢@red75prime,我写了以下内容,但它需要一个不稳定的功能:
#![feature(specialization)]
#![deny(trivial_casts)]
use std::fmt::Debug;
use std::mem;
#[repr(C)]
#[derive(Debug)]
pub struct CVec<T: Sized> {
array: *mut T,
size: usize,
}
unsafe fn unpack_unsafe<T, R>(v: &CVec<T>) -> Vec<R> {
(0..v.size)
.map(|i| mem::transmute_copy(&*v.array.offset(i as isize)))
.collect()
}
pub fn unpack<T, U, F>(v: &CVec<T>, mut f: F) -> Vec<U>
where
F: FnMut(&T) -> U,
{
(0..v.size)
.map(|i| unsafe { f(&*v.array.offset(i as isize)) })
.collect()
}
trait Unpack {
type R: Debug;
fn unpack(&self) -> Vec<Self::R>;
}
impl<T: Debug> Unpack for CVec<T> {
default type R = T;
default fn unpack(&self) -> Vec<Self::R> {
unsafe { unpack_unsafe(self) }
}
}
impl<T: Unpack + Debug> Unpack for CVec<T> {
type R = Vec<T::R>;
fn unpack(&self) -> Vec<Self::R> {
unpack(self, |v| v.unpack())
}
}
fn main() {
let mut vs = [1, 2, 3];
let mut v1 = CVec {
array: vs.as_mut_ptr(),
size: vs.len(),
};
let mut v2 = CVec {
array: &mut v1 as *mut _,
size: 1,
};
let mut v3 = CVec {
array: &mut v2 as *mut _,
size: 1,
};
let v4 = CVec {
array: &mut v3 as *mut _,
size: 1,
};
let v = v4.unpack();
println!("{:?}", v);
let ptr: *mut () = &mut v3 as *mut _ as *mut _;
}
是否可以用稳定的编译器重写它?
重要提示:CVec<T>
实现了 Drop
因为它必须释放分配的 array
内存所以它不能是 Copy
.
在稳定的 Rust 中,特征的实现不能相交,我们不能使用负特征边界。不可能使用像这样的直接实现:
impl<T: Copy> Unpack for CVec<T> { // copies elements }
impl<T: Unpack> Unpack for CVec<T> { // calls `unpack` for elements }
但是我们可以修改特征并利用 CVec
没有实现 Copy
.
的事实
我认为下面的代码是不言自明的。
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CVec<T: Sized> {
array: *mut T,
size: usize,
}
// Unsafe because CVec is not guaranteed to contain valid pointer and size
unsafe fn unpack<T, U, F>(v: &CVec<T>, mut f: F) -> Vec<U>
where
F: FnMut(&T) -> U,
{
(0..v.size)
.map(|i| f(&*v.array.offset(i as isize)))
.collect()
}
trait Unpack {
type Out;
unsafe fn unpack(&self) -> Self::Out;
}
impl<T: Unpack> Unpack for CVec<T> {
type Out = Vec<T::Out>;
unsafe fn unpack(&self) -> Self::Out {
unpack(self, |e| e.unpack())
}
}
impl<T: Copy> Unpack for T {
type Out = T;
unsafe fn unpack(&self) -> Self::Out {
*self
}
}
我正在为 C 库编写包装器,但我一直在编写大量类型,例如 CVecOf<anything>
:
#[repr(C)]
pub struct CVecOfPoint {
pub array: *mut Point2i,
pub size: usize,
}
impl CVecOfPoint {
pub fn rustify(&self) -> Vec<Point2i> {
(0..self.size)
.map(|i| unsafe { *(self.array.offset(i as isize)) })
.collect::<Vec<_>>()
}
}
#[repr(C)]
pub struct CVecOfPoints {
pub array: *mut CVecOfPoint,
pub size: usize,
}
impl CVecOfPoints {
pub fn rustify(&self) -> Vec<Vec<Point2i>> {
(0..self.size)
.map(|i| unsafe {
let vec = &*self.array.offset(i as isize);
vec.rustify()
})
.collect::<Vec<_>>()
}
}
pub struct CVecOfPointsOfPoints;
pub struct CVecOfPointsOfPointsOfPoints;
pub struct CVecOfPointsOfPointsOfPointsOfPoints;
我只想用以下映射规则编写 CVec<T>
:
rustify :=
T -> T
CVec<T> -> Vec<T>
因此 CVecOfPointsOfPointsOfPointsOfPoints
就是 CVec<CVec<CVec<CVec<Cvec<Point>>>>>
。
感谢@red75prime,我写了以下内容,但它需要一个不稳定的功能:
#![feature(specialization)]
#![deny(trivial_casts)]
use std::fmt::Debug;
use std::mem;
#[repr(C)]
#[derive(Debug)]
pub struct CVec<T: Sized> {
array: *mut T,
size: usize,
}
unsafe fn unpack_unsafe<T, R>(v: &CVec<T>) -> Vec<R> {
(0..v.size)
.map(|i| mem::transmute_copy(&*v.array.offset(i as isize)))
.collect()
}
pub fn unpack<T, U, F>(v: &CVec<T>, mut f: F) -> Vec<U>
where
F: FnMut(&T) -> U,
{
(0..v.size)
.map(|i| unsafe { f(&*v.array.offset(i as isize)) })
.collect()
}
trait Unpack {
type R: Debug;
fn unpack(&self) -> Vec<Self::R>;
}
impl<T: Debug> Unpack for CVec<T> {
default type R = T;
default fn unpack(&self) -> Vec<Self::R> {
unsafe { unpack_unsafe(self) }
}
}
impl<T: Unpack + Debug> Unpack for CVec<T> {
type R = Vec<T::R>;
fn unpack(&self) -> Vec<Self::R> {
unpack(self, |v| v.unpack())
}
}
fn main() {
let mut vs = [1, 2, 3];
let mut v1 = CVec {
array: vs.as_mut_ptr(),
size: vs.len(),
};
let mut v2 = CVec {
array: &mut v1 as *mut _,
size: 1,
};
let mut v3 = CVec {
array: &mut v2 as *mut _,
size: 1,
};
let v4 = CVec {
array: &mut v3 as *mut _,
size: 1,
};
let v = v4.unpack();
println!("{:?}", v);
let ptr: *mut () = &mut v3 as *mut _ as *mut _;
}
是否可以用稳定的编译器重写它?
重要提示:CVec<T>
实现了 Drop
因为它必须释放分配的 array
内存所以它不能是 Copy
.
在稳定的 Rust 中,特征的实现不能相交,我们不能使用负特征边界。不可能使用像这样的直接实现:
impl<T: Copy> Unpack for CVec<T> { // copies elements }
impl<T: Unpack> Unpack for CVec<T> { // calls `unpack` for elements }
但是我们可以修改特征并利用 CVec
没有实现 Copy
.
我认为下面的代码是不言自明的。
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CVec<T: Sized> {
array: *mut T,
size: usize,
}
// Unsafe because CVec is not guaranteed to contain valid pointer and size
unsafe fn unpack<T, U, F>(v: &CVec<T>, mut f: F) -> Vec<U>
where
F: FnMut(&T) -> U,
{
(0..v.size)
.map(|i| f(&*v.array.offset(i as isize)))
.collect()
}
trait Unpack {
type Out;
unsafe fn unpack(&self) -> Self::Out;
}
impl<T: Unpack> Unpack for CVec<T> {
type Out = Vec<T::Out>;
unsafe fn unpack(&self) -> Self::Out {
unpack(self, |e| e.unpack())
}
}
impl<T: Copy> Unpack for T {
type Out = T;
unsafe fn unpack(&self) -> Self::Out {
*self
}
}