在 Rust 中获取常量数组长度

Lia*_*ink 1 arrays types iterator rust

由于 Rust 数组长度在编译时已知,我如何获得该长度作为常量整数?可以获得与整个数组对应的切片的非常量 len()。rust 似乎不像 c++ 那样有开始和结束迭代器,而且我不清楚是否可以获取字节长度并将其除以元素的字节大小。我仍然是 Rust 的菜鸟,所以我可能错过了一些东西,但过去几天我一直在寻找一种方法来做到这一点。我知道克隆数组是可能的,但这仅在我想要克隆时才有用,并且与仅从数组类型获取长度相比,迭代数组的每个元素会很慢。我怎样才能做到这一点?Rust 文档说数组的类型签名是[ele_type; ele_number],因此编译器在创建后会跟踪数组的长度。我知道std::any::type_name::()可以用来打印变量的类型,但它的输出不是 const。

\n

我知道已经提出了一个相关问题,但现有答案没有回答我的问题,而且该问题很旧(从 2017 年开始),因此情况可能已经发生变化,并且不太可能向人们建议。

\n

编辑 1添加示例:

\n
fn main()\n{\n    let test_arr = [0.f64; 10];\n    do_something(test_arr);\n\n}\n\nfn do_something<const C: usize>(array: [f64; C])\n{\n    // This causes an error because len() returns a nonconst uint,\n    // and so can\xe2\x80\x99t be used to create new arrays\n    // C can also not be used because it counts as external\n    let triple_size_array = [f64; array.len()*3];\n}\n
Run Code Online (Sandbox Code Playgroud)\n

编辑2:\n为了澄清,可以array = [f64; C];直接执行,但还有其他事情无法执行。如下所示,我无法使用 C 进行任何整数数学运算来定义不同大小的数组,我只能使用泛型参数直接定义数组。

\n
13 | fn ftcs_update<const C: usize>(u: &[f64;C], f: fn(f64)->f64, l: f64)\n   |                      - const parameter from outer function\n14 | {\n15 |     const grid_size: usize = C;\n   |                              ^ use of generic parameter from outer function\n\nerror: aborting due to previous error\n\nFor more information about this error, try `rustc --explain E0401`.\n
Run Code Online (Sandbox Code Playgroud)\n
error: generic parameters may not be used in const operations\n  --> main.rs:16:22\n   |\n16 |     let u_new = [0.; C*3];\n   |                      ^ cannot perform const operation using `C`\n   |\n   = help: const parameters may only be used as standalone arguments, i.e. `C`\n
Run Code Online (Sandbox Code Playgroud)\n

编辑3:\n根据凯文的建议,这个解决方案似乎也不起作用。

\n
error[E0401]: can\'t use generic parameters from outer function\n  --> main.rs:15:30\n   |\n13 | fn ftcs_update<const C: usize>(u: &[f64;C], f: fn(f64)->f64, l: f64)\n   |                      - const parameter from outer function\n14 | {\n15 |     const grid_size: usize = C;\n   |                              ^ use of generic parameter from outer function\n\nerror: aborting due to previous error\n\nFor more information about this error, try `rustc --explain E0401`.\n
Run Code Online (Sandbox Code Playgroud)\n

hcs*_*sch 5

Const 泛型是 Rust 的一个领域,目前仍处于开发阶段,在某些地方它的发展还不如constexprC++ 中的那样。这是其中之一。

const 泛型表达式有一个实现(即可以在编译时计算的表达式,依赖于泛型参数),但这仍然不完整、不稳定,并且仅在 Rust 的夜间版本中可用。有关更多详细信息,请参阅跟踪问题https://github.com/rust-lang/rust/issues/76560 。

这是您的示例,经过修补后可以与当前实现的内容一起使用:

#![feature(generic_const_exprs)]
// We still need this feature and the nightly compiler, because this is still
// in the works and the implementation is incomplete!

fn main() {
    // I changed your array initializers, because you were using the type
    // where a value should have been.
    // The way you wrote them is how you write the type signature for these arrays.
    // I've added the type signature here, but that wasn't necessarily
    // and merely for illustrative purposes. The compiler can infer it here.
    let test_arr: [f64; 10] = [0_f64; 10];
    do_something(test_arr);
}

// The where is still required to constrain this function to values of C where
// C * 3 is a valid size for an array. This might change in the future.
fn do_something<const C: usize>(_array: [f64; C])
where
    [f64; C * 3]: Sized,
{
    // Here you can now just use the generic parameter in an expression.
    // In other places you may have to surround such an expression by curly braces
    // for the sake of syntactical unambiguity.
    let triple_size_array = [0_f64; C * 3];
    println!("{}", triple_size_array.len());
}
Run Code Online (Sandbox Code Playgroud)

这是包含此代码的 Rust 游乐场的链接。

目前,如果省略该where子句,您将收到以下错误,该错误告诉您代码的哪一部分需要约束以及要添加哪些约束:

error: unconstrained generic constant
  --> src/main.rs:22:37
   |
22 |     let triple_size_array = [0_f64; C * 3];
   |                                     ^^^^^
   |
   = help: try adding a `where` bound using this expression: `where [(); C * 3]:`
Run Code Online (Sandbox Code Playgroud)

请注意,为 where 子句建议的元素类型不是f64,而是单位类型 / 0-tuple ()。这是因为对于约束而言,只有作为有效长度的数组长度相关,而不是元素的类型。