如何保证const变量不会溢出?

How can I guarantee that overflow will not occur in const variables?

我可以描述这个 "circular" 六边形网格的维度..

.. 在编译时只定义了 1 个值 n

const GRID_RADIUS: usize = 3;

因此,网格中的单元格数在编译时也是已知的,因为它是 (2n+1)^2-n*(n+1)(这里是 37)。

但是,以下内容:

const N: usize = 3;
const N_CELLS: usize = ((2 * N + 1) ^ 2) - N * (N + 1);

struct Cell;

struct Grid {
    cells: [Cell; N_CELLS],
}

不编译:

error: any use of this value will cause an error
 --> src/main.rs:2:34
  |
2 | const N_CELLS: usize = ((2 * N + 1) ^ 2) - N * (N + 1);
  | -----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
  |                        |
  |                        attempt to subtract with overflow
  |
  = note: `#[deny(const_err)]` on by default

我理解 rustc 担心减去 usize 类型可能会导致溢出,但我可以保证 N_CELLS 在这种情况下总是正数。

我怎样才能对此负责并让rustc信任我?

无法保证 — 常量值在编译时求值。编译器 知道 值是否因为执行计算而溢出。

I understand that rustc worries that subtracting usize types may result in overflow, but I can guarantee that N_CELLS will always be positive in this case.

How can I take responsibility for this and have rustc trust me?

你不能保证这一点(编译器不应该信任你)因为你是不正确的^ 表示异或,而不是“的幂”。编译器执行了您的代码并从字面上减去零以下,从而触发了错误。这不是假设:

((2 * n) ^ 2) = 4
n * (n + 1) = 12
4 - 12 = -8
fn main() {
    let n: usize = 3;
    let n_cells: usize = ((2 * n) ^ 2) - n * (n + 1);
}
thread 'main' panicked at 'attempt to subtract with overflow', src/main.rs:3:26

事实上,thanks to this question,Rust 现在显示导致溢出的值,希望能使原来的错误更清楚:

 --> src/lib.rs:2:24
  |
2 | const N_CELLS: usize = ((2 * N + 1) ^ 2) - N * (N + 1);
  | -----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
  |                        |
  |                        attempt to compute `5_usize - 12_usize` which would overflow
  |
  = note: `#[deny(const_err)]` on by default

另请参阅:

很遗憾,您目前不能在常量中使用 pow

const N: usize = 3;
const N_CELLS: usize = ((2 * N + 1).pow(2)) - N * (N + 1);
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
 --> src/lib.rs:2:24
  |
2 | const N_CELLS: usize = ((2 * N + 1).pow(2)) - N * (N + 1);
  |                        ^^^^^^^^^^^^^^^^^^^^

你必须自己展开乘法:

const N_CELLS: usize = {
    let a = 2 * N + 1;
    let b = N * (N + 1);
    a * a - b
};