首页 文章

我可以在不使用泛型类型的情况下获取多特征实例的特征对象吗?

提问于
浏览
6

我试图获得一个动态可调度的借位到一个实现 ReaderSeek 的对象的实例 .

据我所知,只要涉及一个特征,Rust就可以进行动态调度 .

use std::io::{Read, Seek};
fn user(stream: &mut Read) {}

但是,有两个或更多特征边界,我被迫使用类型参数:

fn user_gen<T: Read + Seek>(stream: &mut T) {}

由于下面的实际类型是构建器,它必须以某种方式存储借用的对象,并且使用类型参数将使实现更复杂(我已经有三个类型参数) .

理想情况下,我可以做这样的事情:

fn user_dynamic(stream: &mut (Read + Seek)) {}

这不编译:

error[E0225]: only auto traits can be used as additional traits in a trait object
 --> src/main.rs:3:38
  |
3 | fn user_dynamic(stream: &mut (Read + Seek)) {}
  |                                      ^^^^ non-auto additional trait

我知道动态调度是通过胖指针完成的,通常它们只引用一个方法表,而不是多个方法表 . 我没有看到过支持这种语言的静态编译语言,但这样的功能对我有很大的帮助 .

1 回答

  • 7

    您可以创建一个合并这两个特征的空特征:

    use std::io::{Read, Seek};
    
    trait SeekRead: Seek + Read {}
    impl<T: Seek + Read> SeekRead for T {}
    
    fn user_dynamic(stream: &mut SeekRead) {}
    

    这将为 SeekRead 创建一个新的vtable,其中包含 SeekRead 的所有函数指针 .

    如果没有一些技巧,你将无法将 &mut SeekRead 转换为 &mut Seek&mut Read (参见Why doesn't Rust support trait object upcasting?

相关问题