gpt4 book ai didi

generics - 是否可以自动实现将特征对象转换为另一个特征对象的特征?

转载 作者:行者123 更新时间:2023-11-29 08:07:45 25 4
gpt4 key购买 nike

我有一个特征可以管理到不同特征对象的转换。特征看起来像这样:(BooGee 都是不同的特征)

trait Foo {
fn as_boo(&mut self) -> Option<&mut Boo> {
None
}

fn as_gee(&mut self) -> Option<&mut Gee> {
None
}
}

为了减少样板代码的数量,我现在想自动将此实现更改为此,以防结构实现 Boo/Gee:

#[derive(Boo)]
struct W {}

impl Foo for W {
fn as_boo(&mut self) -> Option<&mut Boo> {
Some(self)
}
}

如果我只需要使用泛型转换为另一个特征,我就可以这样做:

impl<T: Boo> Foo for T {
fn as_boo(&mut self) -> Option<&mut Boo> {
Some(self)
}
}

但如果我还想为 Gee 自动实现 Foo,由于我无法实现 Foo 两次,据我所知,rust 不支持。

// This does not compile because Foo might get implemented twice.
impl<T: Boo> Foo for T {
fn as_boo(&mut self) -> Option<&mut Boo> {
Some(self)
}
}

impl<T: Gee> Foo for T {
fn as_gee(&mut self) -> Option<&mut Gee> {
Some(self)
}
}

使用 Procedural Macros 或许可以实现这一点但我找不到对它们的任何深入解释,所以我现在有点卡住了。

最佳答案

这个问题可以通过introducing an extra level of indirection来解决:

trait Boo {}
trait Gee {}

trait FooAsBoo {
fn as_boo(&mut self) -> Option<&mut Boo> {
None
}
}

trait FooAsGee {
fn as_gee(&mut self) -> Option<&mut Gee> {
None
}
}

trait Foo: FooAsBoo + FooAsGee {}

impl<T: Boo> FooAsBoo for T {
fn as_boo(&mut self) -> Option<&mut Boo> {
Some(self)
}
}

impl<T: Gee> FooAsGee for T {
fn as_gee(&mut self) -> Option<&mut Gee> {
Some(self)
}
}

impl<T: FooAsBoo + FooAsGee> Foo for T {} // if there's nothing else in Foo

struct W;
impl Boo for W {}
impl Gee for W {}

fn main() {
let mut w = W;
let foo = &mut w as &mut Foo;
let boo = foo.as_boo();
}

通过将 as_booas_gee 移动到各自的特征中,我们避免了重叠的实现。来自 supertraits 的方法在特征对象中可用,因此 Foo 不必重新声明 as_booas_gee


While this works great in cases where Boo and Gee are close to always implemented, it still requires manual implementation when this is not the case. Considering the fact that as_gee should return None in about 80% of all calls in my program this is rather unfortunate.

我们可以使用 specialization 来解决这个问题(从 Rust 1.19 开始不稳定,因此您需要使用夜间编译器)。我们需要将 as_booas_gee 的实现从 trait 定义中移到适用于所有类型的 impl 中,以便所有类型都实现 FooAsBooFooAsGee

#![feature(specialization)]

trait FooAsBoo {
fn as_boo(&mut self) -> Option<&mut Boo>;
}

trait FooAsGee {
fn as_gee(&mut self) -> Option<&mut Gee>;
}

impl<T> FooAsBoo for T {
default fn as_boo(&mut self) -> Option<&mut Boo> {
None
}
}

impl<T> FooAsGee for T {
default fn as_gee(&mut self) -> Option<&mut Gee> {
None
}
}

关于generics - 是否可以自动实现将特征对象转换为另一个特征对象的特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45501780/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com