在 Rust 中构造一个对象数组

Construct an array of objects in Rust

这是我第一个真正有目的的 Rust 程序,但我仍然对语法一头雾水。所以我有这样的特征对象:

trait HC<'a> {
    fn info(&self) -> TestInfo<'static>;
    fn test(&self) -> HCResult<'a>;
}

#[allow(non_camel_case_types)]
struct Test_NTP;
impl<'a> HC<'a> for Test_NTP {
    fn info(&self) -> TestInfo<'static> {
        TestInfo { ... }
    }

    fn test(&self) -> HCResult<'a> {
        ...
    }
}

#[allow(non_camel_case_types)]
struct Test_Last;
impl<'a> HC<'a> for Test_Last {
    fn info(&self) -> TestInfo<'static> {
        TestInfo { ... }
    }

    fn test(&self) -> HCResult<'a> {
        ...
    }
}

我想构建一个由这些定义 HC 特征的对象组成的数组,与 ID 成组,这样我就可以遍历它们并调用它们的 test() 函数。

const HC_TESTS: [(i16, &dyn HC)] = [
    (1, &Test_NTP),
    (2, &Test_Last)
];

我尝试了几种变体,但总是收到“在编译时没有已知大小”错误。我以为将对象放入 Boxes 中可以解决问题,但我得到了同样的错误:

error[E0277]: the size for values of type `[(i16, Box<&'static (dyn HC<'static> + 'static)>)]` cannot be known at compilation time
   --> src/hc.rs:125:17
    |
125 | const HC_TESTS: [(i16, Box<&dyn HC>)] = [
    |                 ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[(i16, Box<&'static (dyn HC<'static> + 'static)>)]`

结构没有任何字段,我使用它们的唯一原因是将 info()test() 函数绑定在一起,我什至不使用 &self ,它们只需要分派虚拟方法。我做错了什么?

你的问题是你不能使用&you actually can,问题是你实际上没有设置数组长度 [(i16, &dyn HC); 2]).

您也可以使用 Box。但是由于 Box::new 不是 const,您需要将其包装在其他一些惰性包装器中,std::lazy::Lazy 不是稳定的 jet 但可以工作:

const HC_TESTS: Lazy<[(i16, Box<dyn HC>); 2]> = Lazy::new(|| [
    (1, Box::new(Test_NTP)),
    (2, Box::new(Test_Last))
]);

Playground

同时您可以使用 once_cell Lazy,效果相同。

另一种选择是将它们全部包装在一个 enum 中,这样您就可以构造它们,并为该枚举实现特征,以便您以后可以使用它:

enum Tests {
    NTP(Test_NTP),
    Last(Test_Last)
}

impl<'a> HC<'a> for Tests {
    fn info(&self) -> TestInfo<'static> {
        match self {
            Self::NTP(e) => e.info(),
            Self::Last(e) => e.info()
        }
    }

    fn test(&self) -> HCResult<'a> {
        match self {
            Self::NTP(e) => e.test(),
            Self::Last(e) => e.test()
        }
    }
}


const HC_TESTS: [(i16, Tests); 2] = [
    (1, Tests::NTP(Test_NTP)),
    (2, Tests::Last(Test_Last))
];

Playground

您的语法略有偏差。错误

the trait `Sized` is not implemented for `[(i16, Box<&'static (dyn HC<'static> + 'static)>)]

指的是最外面的[...],也就是一个slice.

const HC_TESTS: [(i16, Box<&dyn HC>)] =

您将 HC_TESTS 的类型明确设置为 slice,而不是 array。切片总是没有大小,所以编译器会抱怨。你想要的只是

const HC_TESTS: [(i16, Box<&dyn HC>); 2] =

HC_TESTS 的类型设置为恰好两个元素的 array

请注意,此处的其他答案和评论(“对我有用”)也使用此语法。