我可以在不使用泛型类型的情况下获得多特征实例的特征对象吗?
Can I get a trait object of a multi-trait instance without using a generic type?
我正在尝试获取可动态分派的借用对象的实例,同时实现了 Reader
和 Seek
。
我知道 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
我知道动态调度是通过胖指针完成的,通常这些只指一个方法table,而不是多个方法。我还没有看到支持此功能的静态编译语言,但这样的功能对我有很大帮助。
您可以创建一个合并这两个特征的空特征:
use std::io::{Read, Seek};
trait SeekRead: Seek + Read {}
impl<T: Seek + Read> SeekRead for T {}
fn user_dynamic(stream: &mut SeekRead) {}
这将为 SeekRead
创建一个新的 vtable,其中包含 Seek
和 Read
的所有函数指针。
如果不使用一些技巧,您将无法将 &mut SeekRead
转换为 &mut Seek
或 &mut Read
(参见 Why doesn't Rust support trait object upcasting?)
我正在尝试获取可动态分派的借用对象的实例,同时实现了 Reader
和 Seek
。
我知道 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
我知道动态调度是通过胖指针完成的,通常这些只指一个方法table,而不是多个方法。我还没有看到支持此功能的静态编译语言,但这样的功能对我有很大帮助。
您可以创建一个合并这两个特征的空特征:
use std::io::{Read, Seek};
trait SeekRead: Seek + Read {}
impl<T: Seek + Read> SeekRead for T {}
fn user_dynamic(stream: &mut SeekRead) {}
这将为 SeekRead
创建一个新的 vtable,其中包含 Seek
和 Read
的所有函数指针。
如果不使用一些技巧,您将无法将 &mut SeekRead
转换为 &mut Seek
或 &mut Read
(参见 Why doesn't Rust support trait object upcasting?)