在编译时计算一组常量表达式的最大值
Calculating maximum value of a set of constant expressions at compile time
我正在尝试计算 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
链,但我希望有一个更清晰的解决方案。
虽然常量评估不支持 if
或其他控制流程,但有一种方法可以根据二进制条件 select 值:
[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
可用于稳定的编译器。
我正在尝试计算 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
链,但我希望有一个更清晰的解决方案。
虽然常量评估不支持 if
或其他控制流程,但有一种方法可以根据二进制条件 select 值:
[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
可用于稳定的编译器。