rust - 如何在这个结构定义中避免 PhantomData?
问题描述
我有一个看起来像这样的特征:
trait Handler<C> {
fn handle(&self, msg: &Message, connection: &mut C);
}
应该像链接 HTTP 处理程序的中间件一样链接实例:
let handler = FirstHandler {
next: SecondHandler {
next: FinalHandler {},
},
};
每个处理程序类型都可以对类型施加额外的约束C
:
trait ConnectionThatWorksWithFirstHandler {
...
}
struct FirstHandler<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> {
next: H,
_phantom: PhantomData<C>,
}
正如您在此处看到的,我需要一个PhantomData<C>
来避免错误 E0392 ( parameter C is never used
)。但是,PhantomData 在语义上是错误的,因为处理程序没有保存C
. 这很丑陋。例如,我必须手动提供正确的 Sync/Send 特征实现:
unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Send for Handler<C, H> where H: Send {}
unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Sync for Handler<C, H> where H: Sync {}
auto trait 实现会有一个额外的where C: Send/Sync
界限,这里不合适。
是否有替代 PhantomData 允许我对之间的关系进行编码FirstHandler<C>
,C
以便 Rust 编译器很高兴并且我不需要更多unsafe
代码?
我不是在寻找关联的类型。处理程序 trait 及其实现者是在库中定义的,具体类型C
是在使用该库的应用程序中定义的,因此C
处理程序的 trait 实现不能定义具体类型。
这种设计的想法是允许处理程序链累积C
处理程序链中所需的所有特征界限,这样当我有handler
第二个片段中所示的变量时,隐含的特征界限是C: ConnectionThatWorksWithFirstHandler + ConnectionThatWorksWithSecondHandler + ConnectionThatWorksWithFinalHandler
.
解决方案
无需在结构定义处对内部处理程序实施约束。您可以延迟它们,直到您Handler
实现FirstHandler
.
trait Handler<C> {
fn handle(&self, msg: &Message, connection: &mut C);
}
struct FirstHandler<H> {
next: H
}
impl<C, H> Handler<C> for FirstHandler<H>
where
H: Handler<C>,
C: ConnectionThatWorksWithFirstHandler,
{
fn handle(&self, msg: &Message, connection: &mut C) {
//...
}
}
推荐阅读
- javascript - 使用 Google API 自动完成电子邮件地址
- oracle-apex - 访问通过 APEX_ITEM.SELECT_LIST 创建的页面上的项目
- django - 如何在 Django 列表中添加序列号?
- c# - UWP 应用程序的 Azure 服务总线
- spring - 使用 Spring 和 Hibernate 4.3.5 无法正确打印 JSON
- python - 为什么 eval 尝试在 __builtins__ 上下标?
- php - empty() 在 PHP 中使用 isset() 吗?
- c# - 如何使用asp.net从布局视图发布表单?
- apache-spark - 火花铲斗
- django - Gunicorn 访问日志显示空用户