6

我试图在编译时计算 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递归方式构造一个巨大的 s 链的宏,但我希望那里有一个更清洁的解决方案。

4

1 回答 1

10

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

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

这是做什么的

  • 创建要在其中选择的两个元素的数组
  • 创建任意布尔表达式
  • 将所说的表达方式转换为usize
  • 使用该值索引到上面创建的数组

如果条件是则选择第一个元素,如果条件是false则选择第二个元素true

虽然这个方案理论上可以通过对多个 castbool的数学运算计算索引来扩展到任意长度的数组,但似乎更简单地采用函数方式并嵌套上面的表达式:

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可以在稳定的编译器上使用。

于 2018-12-06T08:00:09.910 回答