我能否在不使用泛型类型的情况下获取多个trait实例的trait对象?

23

我正在尝试获取一个动态可分配借用,以访问实现ReaderSeek两个trait的对象实例。

我知道只要涉及一个trait,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

我了解动态分派是通过fat指针实现的,通常这些指针只引用一个方法表而不是多个。我没有见过支持此功能的静态编译语言,但这个特性对我会有很大帮助。

1个回答

30
你可以创建一个空的特质,将这两个特质合并起来:
use std::io::{Read, Seek};

trait SeekRead: Seek + Read {}
impl<T: Seek + Read> SeekRead for T {}

fn user_dynamic(stream: &mut SeekRead) {}

这将创建一个新的vtable,其中包含SeekRead的所有函数指针,用于SeekRead
您无法直接将&mut SeekRead强制转换为&mut Seek&mut Read,需要一些技巧(请参见为什么Rust不支持trait对象向上转型?)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接