rust 在编译时计算一组常量表达式的最大值

qacovj5a  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(122)

我试图在编译时计算Rust过程宏(派生宏)中一组常量的最大值。
宏看起来像这样:

fn get_max_len() -> TokenStream {
    // Each TokenStream represents a constant expression
    let len: Vec<TokenStream> = get_constant_lengths();

    quote! {
      // #(#len),* gets expanded to #len[0], #len[1], #len[2]...
      const LEN: usize = std::cmp::max(#(#len),*);
    }
}

字符串
问题是std::cmp::max是一个函数,因此不能在常量表达式中使用(至少在const fn稳定之前-如果可能的话,我希望保持稳定的Rust)。
如何在编译时计算一组常量的最大值?
我也许可以写一个max!宏,基本上递归地构造一个巨大的if链,但我希望有一个更清晰的解决方案。

1wnzp6jl

1wnzp6jl1#

虽然常量求值不支持if或其他控制流,但有一种方法可以根据二进制条件选择值:

[a, b][(a < b) as usize]

字符串
这所做的是

  • 创建一个包含两个元素的数组
  • 创建任意布尔表达式
  • 将所述表达式转换为usize
  • 使用该值索引到上面创建的数组中

如果条件是false,则选择第一个元素,如果条件是true,则选择第二个元素。
虽然这个方案在理论上可以通过对多个转换的bool s进行数学运算来计算索引,从而扩展到任意长度的数组,但似乎更简单的方法是使用函数的方式嵌套上面的表达式:

const fn max(a: usize, b: usize) -> usize {
    [a, b][(a < b) as usize]
}

const MAX: usize = max(max(max(5, 6), 42), 3);


从Rust 1.31开始,const fn可以在稳定编译器上使用。

wgmfuz8q

wgmfuz8q2#

我认为值得注意的是,“一个巨大的if链”现在是完全可能的。不断 * 评估 * 表达式的列表是here

相关问题