rust - 从没有 Self 类型的序数中获取通用特征?

标签 rust

我有两个特征,一个是序数 ( Foo ),另一个是通用 ( TypedFoo<T> )。我有几个结构,每个结构都实现了两个特征。

是否可以从 Foo 转换至 TypedFoo<T> , 不转换为中间结构?

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))];    
} 

我可以改变Foo对此:

trait Foo {
    fn f(&mut self);
    fn get_self(&self) -> &Any;
}

然后得到v[0].get_self() downcast_refData , 然后 Data&TypedFoo<Data> .

但是有没有可能得到&TypedFoo<Data>来自 &Foo在不知道“数据类型”的情况下,Any 的一些模拟但是为了一个特质。

我想象这样的语法:

let foo: &Foo = ...;
if let Some(typed_foo) = foo.cast::<Data>() {

} 

我的问题不同于Can I cast between two traits? 因为我有一个通用特征和一个顺序特征。如果我有两个序数特征,那么解决方案将很简单:

trait Foo {
    fn f(&mut self);
    fn as_typed_foo(&self) -> &TypedFoo;
}

TypedFoo是通用的,该问题的答案都没有帮助我。一种可能的解决方案是:

trait Foo {
    fn f(&mut self);
    fn cast(&mut self, type_id: ::std::any::TypeId) -> Option<*mut ::std::os::raw::c_void>;
}

我不确定投 *mut TypedFoo<T> 有多安全-> *mut ::std::os::raw::c_void然后回到*mut TypedFoo<T> .

最佳答案

你想要的函数的签名是

fn convert<T>(x: &Box<Foo>) -> &TypedFoo<T>

为了类型检查这个签名编译器必须知道 Box 里面的类型工具 TypedFoo<T>对于一些 T .但是转换为 trait-object 会删除有关真实类型的信息。这意味着不可能静态类型检查此函数的签名。

所以我们需要动态地进行,如果我们想使用当前 crate 不知道的类型,我们需要求助于 unsafe。

一个选项是限制一组类型,可以在TypedFoo中使用, 并在 Foo 中提供转换函数特征。这样可以避免不安全。

Playground link

第二个选项是添加到 trait Foo一个函数,它返回一个对 (TypeId, *const ()) 的切片.该指针是指向函数的类型删除指针,它进行实际转换。转换函数查找所需的类型标识符并执行相应的函数。

Playground link

为了演示,我使用了 Vec而不是切片 conversion_registrar .但是将返回类型更改为 &'static [(TypeId, *const ())] 应该不会太难, 使用 lazy_static crate 。

关于rust - 从没有 Self 类型的序数中获取通用特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44368642/

相关文章:

rust - 在 Rust 中给一个方法作为参数(Vec sort() 方法)

rust - 从 Actix Web 应用程序中间件访问应用程序状态

error-handling - 如何跟踪错误结果的原因?

rust - 在 Rust 中对字符串进行分区

list - 在 self 上指定生命周期时,Rust 在 trait 上使用动态多态性的问题

vector - 如何编写一个函数,将元素添加到向量中,并允许在插入之前更改元素?

debugging - 如何在调试 MSVC ABI Rust 程序时检查变量值?

objective-c - Rust bindgen clang 错误,此 __builtin_neon 函数的常量不兼容

rust - 在闭包内使用 Vector,无需克隆

file - 在 Rust 中迭代文件字节的更快方法是什么?