rust - 当特征函数依赖于为 Self 实现的通用标记特征时,实现通用包装器

标签 rust traits

我目前不知道如何协调 Rust 中的某种设计模式。该模式涉及具有通用功能的特征,该功能受到某些标记特征的限制。 对于这个问题,假设不可能修改 FooFooMarker .我已经知道do_foo应该被放置在一个单独的特征中,而不是使用标记特征,但我不是做出这个决定的人。

trait Foo {
    fn do_foo<T>(&mut self, _: &T) where Self: FooMarker<T>;
    fn do_bar(&mut self);
}

/// Indicates that a specific type is supported for doing Foo.
trait FooMarker<T>: Foo {}

乍一看这可能看起来很合理,但尝试以通用方式使用此模式感觉几乎是不可能的。例如,采用扩展 Foo 功能的包装器结构的通常微不足道的情况。 。最初我认为这个实现可能会按预期工作,但它遇到了许多问题。

struct FooWrapper<F> {
    inner_foo: F
}

impl<F: Foo> Foo for FooWrapper<F> {
    fn do_foo<T>(&mut self, x: &T) where Self: FooMarker<T> {
        do_extra_stuff();
        self.inner_foo.do_foo(x)
    }

    fn do_bar(&mut self) {
        self.inner_foo.do_bar();
    }
}

impl<T, F: FooMarker<T>> FooMarker<T> for FooWrapper<F> {}

Rust Playground
从概念上讲,我们也许可以看看这个并知道 FooWrapper<F>: FooMarker<T>意味着F: FooMarker<T> ,但编译器不想依赖此信息。想了想,这倒是有几分道理。无处 impl Foo for FooWrapper我们需要F: FooMarker<T>吗? .

我该如何写FooWrapper 无需重写 FooFooMarker

最佳答案

恐怕你不能,除非我遗漏了一些东西。

impl<T, F: FooMarker<T>> FooMarker<T> for FooWrapper<F> {}告诉我们如果F实现FooMarker<T> ,然后FooWrapper<F>也有。但反之则不一定成立,如下所示:

struct Bar;
struct Baz;

impl Foo for FooWrapper<Bar> {
    fn do_foo<T>(&mut self, _: &T)
    where
        Self: FooMarker<T>
    {}
}

impl FooMarker<Baz> for FooWrapper<Bar> {}

我们无法更改 where子句,因为它是在 Foo 的声明中定义的.


对我来说真正的解决方案是制作 Foo本身是通用的,我理解你正在考虑:

trait Foo<T> {
   fn do_foo(&mut self, _: &T);
}

坦率地说,我从未见过这样的“标记”模式(除非可能涉及密封特征的上下文,不确定),而且我不知道它有什么帮助。

关于rust - 当特征函数依赖于为 Self 实现的通用标记特征时,实现通用包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75138283/

相关文章:

rust - 使用 serde,是否可以反序列化为实现类型的结构?

rust - C++ 的 shared_from_this 在 Rust 中的等价物是什么?

rust - 柴油。火箭和火箭.rs : don't understand why it wants a databases table

compiler-errors - 为什么使用 f32::consts::E 会给出错误 E0223 但 std::f32::consts::E 不会?

python - 获取特质听众列表——谁在听我的特质?

数据库连接包的 Rust 生命周期

c++ - 静态链接启用了PIC的内置库时,链接器PIC错误

php - 如何将特征与与继承的静态方法冲突的非静态方法一起使用?

scala - 包装所有抛出的异常

带有特征的 PHP 命名空间问题