如何在 Rust 中定义具有不同 const 参数的结构族?

How to define a family of structs with different const parameters in Rust?

我 运行 在读取页表的结构定义时遇到了这个问题(用于面向 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 板条箱,它的工作方式与您尝试的类似,但会为您完成所有 type-level 样板文件。

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,...