微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决如何在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()
    );
}

类型U0U1U2,...表示无符号整数0、1、2,...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。