首页 > 解决方案 > 范围内的常量数组

问题描述

如何生成一个长 const 数组,其中的值取自一个范围?奖励:1) 使用 no_std,2) 不使用任何 crate

我想做的事:

struct A {
    a: i32,
    b: B
}

enum B {
    One,
    Two
}

const AS: [A; 1024] = [A{a: 1, b: B::One}, A{a: 2, b: B::One}, ..., A{a: 1024, b: B::One}]

到目前为止,我得到的最远的是:

macro_rules! generate_list {
    ($($a:expr)+, $variant:expr) =>  {
        [ $( A { a: $a, b: $variant } )* ]
    }
}
const AS: [A; 1024] = generate_list!(1..1025i32, B::One);

至少有一个问题似乎是在范围表达式扩展为文字列表之前对宏进行了评估。

标签: arraysrustconstantscompile-timerust-no-std

解决方案


我不确定它是否惯用,但也许以下内容可能适用于您的用例:

#[derive(Debug, Copy, Clone)]
pub struct A {
    a: i32,
    b: B,
}

#[derive(Debug, Copy, Clone)]
pub enum B {
    One,
    Two,
}

const fn gen_array<const N: usize>(offset: i32, b: B) -> [A; N] {
    let mut res = [A { a: offset, b }; N];
    
    let mut i = 0;
    while i < N as i32 {
        res[i as usize].a = offset + i;
        i += 1;
    }
    
    res
}

const AS: [A; 42] = gen_array(0, B::One);

fn main() {
   println!("{:#?}", AS);
}

操场

我使用了一个while循环,因为for当前不允许在const上下文中使用循环E0744

以上将生成 42AS个偏移量为 的值0

[
    A {
        a: 0,
        b: One,
    },
    A {
        a: 1,
        b: One,
    },
    ...
    A {
        a: 41,
        b: One,
    },
]

Godbolt编译器资源管理器显示它生成的指令与手动编写它的指令相同。


推荐阅读