Rust 从没有自我类型的序号1中获取泛型特征?
我有两个特点,一个是序数(Rust 从没有自我类型的序号1中获取泛型特征?,rust,Rust,我有两个特点,一个是序数(Foo),另一个是泛型(TypedFoo)。我有几个结构,每个结构都实现了这两个特性 是否可以从Foo转换为TypedFoo,而不转换为中间结构 trait Foo { fn f(&mut self); } trait TypedFoo<T> { fn get(&self) -> T; } #[derive(Clone)] struct Data(i32); impl Foo for Data { fn f
Foo
),另一个是泛型(TypedFoo
)。我有几个结构,每个结构都实现了这两个特性
是否可以从Foo
转换为TypedFoo
,而不转换为中间结构
trait Foo {
fn f(&mut self);
}
trait TypedFoo<T> {
fn get(&self) -> T;
}
#[derive(Clone)]
struct Data(i32);
impl Foo for Data {
fn f(&mut self) {
self.0 += 1;
}
}
impl TypedFoo<Data> for Data {
fn get(&self) -> Data {
self.clone()
}
}
//struct Data2(f64);
//impl Foo for Data2...
//impl TypedFoo<Data2> for Data2..
fn main() {
let v: Vec<Box<Foo>> = vec![Box::new(Data(1))];
}
然后获取v[0]。获取self()
但是从&Foo
获得&TypedFoo
而不知道“数据类型”是不是可能的,这是任何
的一个类似物,只是为了一个特征
我想象这样的语法:
let foo: &Foo = ...;
if let Some(typed_foo) = foo.cast::<Data>() {
}
因为TypedFoo
是通用的,所以这个问题的答案对我没有帮助。一种可能的解决办法是:
trait Foo {
fn f(&mut self);
fn cast(&mut self, type_id: ::std::any::TypeId) -> Option<*mut ::std::os::raw::c_void>;
}
trait Foo{
fn f(和mut self);
fn cast(&mut self,type_id:::std::any::TypeId)->选项;
}
我不确定强制转换*mut-TypedFoo
->*mut::std::os::raw::c_void
,然后返回到*mut-TypedFoo
所需函数的签名是
fn convert<T>(x: &Box<Foo>) -> &TypedFoo<T>
fn转换(x:&Box)->&TypedFoo
要进行类型检查,此签名编译器必须知道框中的类型对某些T
实现TypedFoo
。但是转换成trait对象会删除关于真实类型的信息。这意味着不可能对该函数的签名进行静态类型检查
所以我们需要动态地做,如果我们想使用当前板条箱不知道的类型,我们需要求助于不安全的方法
一个选项是限制可在TypedFoo
中使用的一组类型,并在Foo
特性中提供转换函数。这样可以避免不安全
第二个选项是添加到trait Foo
函数,该函数返回一个成对的切片(TypeId,*const())
。指针是指向函数的类型擦除指针,它执行实际转换。转换函数搜索所需的类型标识符并执行相应的函数
为了演示,我使用了Vec
而不是conversion\u register
中的slice。但是使用lazy_static板条箱将返回类型更改为&'static[(TypeId,*const())]
应该不会太难@Shepmaster我更新了我的问题,以解释它与您提到的问题有何不同。谢谢,看起来我说得不清楚,但对于特定的数据而言,特定的Foo
只能转换为TypedFoo
,而不能转换为多个TypedFoo
,TypedFoo
。理论上,如果函数返回指针,编译器是否会生成错误的代码,但我们将其称为返回引用的函数?@user1244932,如果要为框返回TypedFoo
,其中T
是此特定框中traitFoo
后面的类型,则不可能,因为返回值的类型不能依赖于输入参数的值。Rust不是动态类型语言。您可以通过定义不同类型的&TypedFoo
值的枚举来获得最接近的结果。如果需要克隆Box
,可以将functionfn clone\u Box(&self)->Box
添加到traitFoo
@user1244932,我怀疑将函数指针转换为具有不同签名的函数指针并调用它是未定义的行为。请注意,在我给出的示例中,我将*const()
转换为与原始签名相同的函数指针。
trait Foo {
fn f(&mut self);
fn cast(&mut self, type_id: ::std::any::TypeId) -> Option<*mut ::std::os::raw::c_void>;
}
fn convert<T>(x: &Box<Foo>) -> &TypedFoo<T>