如何解决如何在Rust中定义具有不同const参数的结构家族?
在读取页表的结构定义时遇到了这个问题(在面向x86_64平台的操作系统源代码中使用)。定义如下所示:
pub trait TableLevel {}
pub enum Level4 {}
pub enum Level3 {}
pub enum Level2 {}
pub enum Level1 {}
impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}
pub trait HierarchicalLevel: TableLevel {
type NextLevel: TableLevel;
}
impl HierarchicalLevel for Level4 {
type NextLevel = Level3;
}
impl HierarchicalLevel for Level3 {
type NextLevel = Level2;
}
impl HierarchicalLevel for Level2 {
type NextLevel = Level1;
}
这段Rust代码似乎不太聪明。我想知道是否可以参数化级别编号,例如1,2,3,4。使用C ++,我可以轻松实现:
#include <type_traits>
#include <iostream>
template <unsigned L>
struct Level {
typedef Level<L-1> NextLevel;
};
template <>
struct Level<1> {};
int main() {
// The output below will give "1".
// It checks the type `Level<3>::NextLevel::NextLevel`
// and the type `Level<2>::NextLevel` are indeed the same type.
std::cout
<< std::is_same<Level<3>::NextLevel::NextLevel,Level<2>::NextLevel>::value
<< std::endl;
return 0;
}
我试图在Rust中做同样的事情,但是我做不到,因为Rust不允许我对常量参数进行算术运算。
#![feature(min_const_generics)]
struct Level<const LEVEL: usize> {}
impl <const LEVEL: usize> TableLevel for Level<LEVEL> {}
impl <const LEVEL: usize> HierarchicalLevel for Level<LEVEL> {
// Error message from the compiler:
// generic parameters may not be used in const operations
// cannot perform const operation using `LEVEL`
// help: const parameters may only be used as standalone arguments,i.e. `LEVEL`
type NextLevel = Level<{LEVEL - 1}>;
}
是否可以在Rust的当前版本中(可能是每晚)对级别编号进行参数化设置?
解决方法
不稳定的语言功能min_const_generics
在允许您执行的操作上非常有限。如您所知,您不能在类型参数中使用涉及泛型常量的表达式。
但是,在稳定的Rust中,您可以使用typenum
板条箱,该板条箱的工作方式与您尝试的板条箱类似,但是可以为您完成所有类型级别的样板操作。
use std::ops::Sub;
use typenum::{Unsigned,U1,U2,U3}; // 1.12.0
struct Level<N: Unsigned>(N);
impl<N: Unsigned> Level<N> {
fn value() -> usize {
N::to_usize()
}
}
trait HierarchicalLevel {
type NextLevel;
}
impl<N> HierarchicalLevel for Level<N>
where
N: Sub<U1> + Unsigned,<N as Sub<U1>>::Output: Unsigned,{
type NextLevel = Level<<N as Sub<U1>>::Output>;
}
fn main() {
assert_eq!(
<Level::<U3> as HierarchicalLevel>::NextLevel::value(),Level::<U2>::value()
);
}
类型U0
,U1
,U2
,...表示无符号整数0、1、2,...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。