Rust 是否支持具有运行时确定值的 const 泛型类型?

b0f*_*0fh 4 rust const-generics

考虑 const 通用数据结构的经典示例:方阵。

struct Matrix<T, const N: usize> {
    inner: [[T; N]; N]
}
Run Code Online (Sandbox Code Playgroud)

我想返回一个其 const 参数是动态定义的结构:

fn read_matrix() -> ??? {
    let n: usize = todo!() // the N is decided dynamically
    let r: Box<Matrix<u8, {n}>> = todo!();
    r
}
Run Code Online (Sandbox Code Playgroud)

但:

  • Rust 会抱怨这n不是一个常数
  • 我无法编写适当的返回类型:fn read_matrix<const N: usize>() -> Matrix<u8, N>还不够,因为它让调用者选择 N,而我希望 N 在运行时确定。

我可以通过定义一个特征来解决第二个限制:

trait DynamiMatrix {
   fn size(&self) -> usize;
   fn some_method(&self);
   ...
}

impl<T, const N: usize> DynamicMatrix for Matrix<T,N> {
   fn size(&self) -> usize { N };
   fn some_method(&self){ ... }
   ...
}
Run Code Online (Sandbox Code Playgroud)

但是,对于构建,我能尝试的最好方法是:

fn read_array_pair() -> Box<dyn DynamicMatrix> {
  let n: usize = todo!();
  let m = Box::new(Matrix { inner: [[0; n]; n] });
  todo!(); // fill up m
  m
}
Run Code Online (Sandbox Code Playgroud)

Rust 仍然会抱怨 n 不是常数。

有什么办法可以实现这一点吗?如果可能的话,不要退回到嵌套Vecs,因为我希望强制执行我的平方不变量?

E_n*_*ate 5

Const 参数是经过精心设计的,以便它们在编译时始终是已知的。就像程序中有关类型的大多数信息一样,编译器将删除它们,而不在运行时保留这些信息。因此,简短的回答是否定的,并且不太可能出现在运行时指定此类 const 参数的直接方法。

然而,有一些已知的解决方法可以创建可能包含编译时或运行时信息的泛型结构,它们甚至早于 const 参数。

考虑以下的简化定义ndarray::ArrayBase

pub struct ArrayBase<S, D> {
    /// Data buffer / ownership information. (If owned, contains the data
    /// buffer; if borrowed, contains the lifetime and mutability.)
    data: S,
    /// The lengths of the axes.
    dim: D,
    /// The element count stride per axis.
    strides: D,
}
Run Code Online (Sandbox Code Playgroud)

该定义根据其元素来源 S及其维度进行参数化DD,通常通过原语实现Dim,然后将在这两种情况下通用:

  • 对于固定数量的维度,例如 in Array2D= Ix2,使用户能够传递 a[usize; 2]来索引数组中的元素。
  • 如果编译时维数未知,则可以将Deref 的任何内容传递给 a 进行索引ArrayD,其中D=IxDyn和用户可以将任何内容传递给 a[usize]进行索引。

结论是,您可能有兴趣更改结构和特征的设计,以便将这些详细信息(无论是在编译时还是在运行时推断)编码在类型参数而不是 const 参数中。