简体   繁体   中英

Calculating maximum value of a set of constant expressions at compile time

I'm trying to calculate the maximum value of a set of constants at compile time inside a Rust procedural macro (a derive macro).

The macro looks something like:

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),*);
    }
}

The problem is that std::cmp::max is a function and hence can't be used inside a constant expression (at least until const fn is stabilized - I want to keep to stable Rust if at all possible).

How can I calculate the max of a set of constants at compile-time?

I might be able to write a max! macro that basically constructs a huge chain of if s recursively, but I'm hoping there is a cleaner solution out there.

While constant evaluation does not support if or other control flow, there is a way to select values depending on binary conditions:

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

What this does is

  • create an array of the two elements you want to choose between
  • create an arbitrary boolean expression
  • cast said expresison to a usize
  • use that value to index into the array created above

The first element is chosen if the condition is false , the second element is chosen if the condition is true .

While this scheme can theoretically be extended to arbitrary length arrays by computing indices via mathematical operations on multiple casted bool s, it seems simpler to just go the functional way and nest the above expression:

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

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

Starting with Rust 1.31, const fn is usable on the stable compiler.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM