我需要在Rust类型系统中封装常量。理想情况下,RFC2000将准备就绪,但是在没有它的情况下,并且由于我只需要一组受限制的常量,因此我可以实现一些与我需要的接近的东西:
trait U32Const {
const VAL: u32;
}
struct U32Const10;
impl U32Const for U32Const10 {
const VAL: u32 = 10;
}
struct MyType<X: U32Const> {
val: u32,
template: X,
}
impl<X: U32Const> MyType<X> {
fn do_something(&self) -> u32 {
self.val * X::VAL
}
}
fn main() {
let a = MyType::<U32Const10> {
val: 20,
template: U32Const10 {},
};
println!("{}", a.do_something());
}
根据需要打印出200
-也就是说,常量值来自在main
内部实例化时传入的类型。
现在,这有点谨慎,因为它要求在结构中创建X
的实例,我将其称为template
,然后将其未使用,因此会收到编译器警告。
[如果删除了理想的API template
字段,则编译器会抱怨X
上未使用的参数struct MyType < X: U32Const >
。如果我放弃了X
上的struct MyType
参数,则可以在unexpected type argument
块中的MyType
上得到一个impl
。
是否有某种方法可以使编译器保持满意状态?实际上,我想要一个用于内部const
的only
我需要在Rust类型系统中封装常量。理想情况下,RFC2000应该已经准备就绪,但是在没有它的情况下,并且由于我只需要一组受限制的常量,因此我可以实现接近...
不是将幻像变量提供给结构,而是使用关联的类型可以解决问题,
trait U32Const {
type U32;
const VAL: Self::U32;
}
struct U32Const10;
impl U32Const for U32Const10 {
type U32 = u32;
const VAL: Self::U32 = 10;
}
struct MyType<X: U32Const> {
val: X::U32,
}
impl<X: U32Const<U32 = u32>> MyType<X> {
fn do_something(&self) -> X::U32 {
self.val * X::VAL
}
}
fn main() {
let a = MyType::<U32Const10> { val: 20 };
println!("{}", a.do_something());
}
您可以通过声明template
具有类型PhantomData::<X>
来摆脱编译器警告:
[从playground开始工作,并基于他在注释中加入的@ÖmerErden's answer,对此还有另一种解决方案,即定义一个特征,该特征使用link模式并避免中间类型来引起方差: