我想要 32 位系统上 4 字节的类型和 64 位系统上 8 字节的类型。这是因为我正在将此通用值转换为 usize,无论平台如何,它都必须是有效的转换。
对于这个问题,我正在做一些指针嬗变,以优化作业系统。
struct Job {
job: fn(usize),
args: usize,
}
创建新作业时,我接受任何
fn(T)
和参数 T
,其中 size_of::<T>()
与 size_of::<usize>()
相同,因为然后我会将它们转换为存储在作业中的内容。
但是,问题是我的硬件是 64 位,因此
size_of::<usize>()
的计算结果为 8
,因此允许使用 u64
参数创建作业。但是,如果我要编译为 32 位架构,那么突然就无法编译了。
有没有办法创建只允许指针大小的类型的类型约束,即
Box<T>
、&T
、&mut T
、usize
、*mut T
等?
目前这是我的类型约束:
#![feature(generic_const_exprs)]
pub struct NumConst<const NUM: usize>;
pub trait Is<const NUM: usize> {}
impl<const NUM: usize> Is<NUM> for NumConst<NUM> {}
pub fn with_args<Args>(job: fn(Args), args: Args) -> Job
where NumConst<{ size_of::<Args>() }>: Is<{ size_of::<usize>() }>
, Args: 'static + Send {
// ...
}
这不是可能对特定大小的类型是通用的?的重复,因为我特别询问是否有一种方法可以强制仅将依赖大小的类型作为通用约束。
有没有办法创建只允许指针大小的类型的类型约束,即
,Box<T>
,...&T
这是可能的,虽然不是很漂亮:
pub fn with_args<Args>(_job: fn(Args), _args: Args) -> Job {
struct Check<T>(T);
impl<T> Check<T> {
const PTR_SIZED: () = assert!(std::mem::size_of::<T>() == std::mem::size_of::<usize>());
}
let _ = Check::<Args>::PTR_SIZED;
todo!()
}
pub fn useit() {
with_args(drop, &123); // pointer-sized, compiles
//with_args(drop, 1u128); // non-pointer-sized, doesn't compile
}
此外,正如评论中所指出的,请注意,大小并不是有效嬗变的唯一标准。