Вычисление максимального значения набора константных выражений во время компиляции - PullRequest
0 голосов
/ 04 декабря 2018

Я пытаюсь вычислить максимальное значение набора констант во время компиляции внутри процедурного макроса 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, но яЯ надеюсь, что есть более чистое решение.

1 Ответ

0 голосов
/ 06 декабря 2018

Хотя постоянная оценка не поддерживает if или другой поток управления, существует способ выбора значений в зависимости от бинарных условий:

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

Для этого используется

  • создайте массив из двух элементов, которые вы хотите выбрать между
  • создайте произвольное логическое выражение
  • приведите указанное выражение к usize
  • используйте это значение для индексации вмассив, созданный выше

Первый элемент выбирается, если условие false, второй элемент выбирается, если условие true.

Хотя эта схема теоретически можетЕсли использовать массивы произвольной длины, вычисляя индексы с помощью математических операций для нескольких приведенных bool с, то проще просто пойти функциональным путем и вложить указанное выше выражение:

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 можно использовать в стабильном компиляторе.

...