gpt4 book ai didi

generics - 通用特征对象的向量

转载 作者:行者123 更新时间:2023-11-29 08:28:38 24 4
gpt4 key购买 nike

(这是我第二次尝试找出我的确切问题。查看编辑历史记录)

我有一个简单的通用特征和两个不同的实现:

pub trait MyTrait<T=Self> where T: MyTrait {
}

struct Impl1;
impl MyTrait for Impl1 {
}

struct Impl2;
impl MyTrait for Impl2 {
}

我现在想要一个包含两个实现元素的向量。据我了解here ,我这样做:

fn foo() {
let mut traits: Vec<Box<MyTrait>> = Vec::new();
traits.push(Box::new(Impl1{}));
traits.push(Box::new(Impl2{}));
}

但是编译器不同意:

error[E0393]: the type parameter `T` must be explicitly specified
--> src/main.rs:25
|
25 | let mut traits: Vec<Box<MyTrait>> = Vec::new();
| ^^^^^^^ missing reference to `T`
|
= note: because of the default `Self` reference, type parameters must be specified on object types

一方面,这是有道理的。另一方面,我应该为 T 放什么? ?我希望这是通用的,所以我不能简单地放在那里 Impl1Impl2 .我可以做Vec<Box<MyTrait<MyTrait>>> , 但这只会移动错误,而不会解决错误。


编辑

上面的代码是最小的失败代码,这里是一个稍微不那么简单的实现:

enum MyEnum<T: MyTrait> {
A(T),
B
}

pub trait MyTrait<T=Self> where T: MyTrait {
fn do_stuff(self) -> MyEnum<T>;
}

struct Impl1;
impl MyTrait for Impl1 {
fn do_stuff(self) -> MyEnum<Impl1> {
MyEnum::A(self)
}
}

struct Impl2;
impl MyTrait for Impl2 {
fn do_stuff(self) -> MyEnum<Impl2> {
MyEnum::B
}
}

每个MyTrait对象消耗自身并可能导致 MyEnum::A包含另一个 MyTrait对象或 MyEnum::B .

最佳答案

通用的东西——无论是特征、类型还是函数——都不是可以寻址的代码,而只是当你替换它们时生成的代码模板。所以它们不是“对象安全的”,即你不能将它们用于动态引用和智能指针的类型。您只能使用它们的特定实例。

MyTrait是通用的,所以你不能有 &dyn MyTraitBox<dyn MyTrait> .你只能有 &dyn MyTrait<Impl1>Box<dyn MyTrait<Impl1>> .

您确实有参数的默认值,但是 Self很特别,因为Self是实现特征的类型,因此只在 impl 中有意义定义。但不在您尝试声明 Vec<Box<MyTrait>> 的自由函数中.这就是它无法编译的原因。

也因为有多特别Self是,impl MyTrait for Impl1脱糖为 impl MyTrait<Impl1> for Impl1impl MyTrait for Impl2脱糖为 impl MyTrait<Impl2> for Impl2 .自 MyTrait<Impl1>MyTrait<Impl2> 的特征不同, Impl1 没有共同特征和 Impl2您可以使用它们来装箱并将它们放在一个公共(public)向量中。

您需要一个具体,即非通用的动态多态性特征。

关于generics - 通用特征对象的向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57316518/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com