我有一个标记特征,它有一个关联的常量:

trait Trait {
    const N: usize;
}

我有一个由特征限定的泛型类型.我希望能够在声明中使用N:

struct S<T: Trait> {
    field: [f64; T::N],
}

我的期望是,对于任何指定NTrait实现,我可以拥有一个S,其中包含相同数量的浮点array.相反,我得到以下编译器错误:

error: generic parameters may not be used in const operations
 --> src/main.rs:8:18
  |
8 |     field: [f64; T::N],
  |                  ^^^^ cannot perform const operation using `T`
  |
  = note: type parameters may not be used in const expressions

error[E0392]: parameter `T` is never used
 --> src/main.rs:7:10
  |
7 | struct S<T: Trait> {
  |          ^ unused parameter
  |
  = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

For more information about this error, try `rustc --explain E0392`.

虽然我理解错误本身,但我不理解它的原因或如何绕过它.

推荐答案

使用关联类型的另一种解决方案是使用typenum个整数:

use nalgebra::base::dimension::{ToConst, U1};
use nalgebra::base::storage::{IsContiguous, RawStorageMut, Storage};
use nalgebra::base::{Matrix, Scalar};

trait ToVectorArrayStorage: ToConst {
    type ArrayStorage<T: Scalar>: RawStorageMut<T, <Self as ToConst>::Const>
        + Storage<T, <Self as ToConst>::Const>
        + IsContiguous;
}

macro_rules! impl_to_vector_array_storage {
    ( $( $num:literal => $typenum:ident, )* ) => {
        $(
            impl ToVectorArrayStorage for typenum::$typenum {
                type ArrayStorage<T: Scalar> = nalgebra::base::ArrayStorage<T, $num, 1>;
            }
        )*
    }
}
impl_to_vector_array_storage! {
    0=>U0, 1=>U1, 2=>U2, 3=>U3, 4=>U4, 5=>U5, 6=>U6, 7=>U7, 8=>U8, 9=>U9, 10=>U10,
    11=>U11, 12=>U12, 13=>U13, 14=>U14, 15=>U15, 16=>U16, 17=>U17, 18=>U18,
    19=>U19, 20=>U20,
}

trait Trait {
    type N: ToVectorArrayStorage;
}

type TypenumVector<T, N> =
    Matrix<T, <N as ToConst>::Const, U1, <N as ToVectorArrayStorage>::ArrayStorage<f64>>;

struct S<T: Trait> {
    field: TypenumVector<f64, T::N>,
}

Playground.

Rust相关问答推荐

在‘await’点上使用‘std::同步::Mutex’是否总是会导致僵局?

为什么单元类型(空元组)实现了`Extend`trait?

如何为utoipa中的可选查询参数生成OpenAPI模式?

为什么BitVec缺少Serialize trait?

Rust&;Tokio:如何处理更多的信号,而不仅仅是SIGINT,即SIGQUE?

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

为什么TcpListener的文件描述符和生成的TcpStream不同?

如何在不调用Collect()的情况下为新型vec实现IntoIterator?

JSON5中的变量类型(serde)

在文件链实施中绕过borrow 判断器

是否提供Bundle 在可执行文件中的warp中的静态文件?

当我编译 Rust 代码时,我是否缺少 AVX512 的目标功能?

Rust 中的静态引用

如何从borrow 的异步代码运行阻塞代码?

为什么1..=100返回一个范围而不是一个整数?

如何将切片推入数组?

如何在 C++ 和 Rust 之间共享 pthread 同步原语?

通用类型,不同于输入类型,作为函数的返回值

在使用大型表达式时(8k 行需要一小时编译),是否可以避免 Rust 中的二次编译时间?

为什么我返回的 impl Trait 的生命周期限制在其输入的生命周期内?