我现在对如何协调Rust中的某个设计模式感到困惑.该模式涉及一个具有一般功能的特征,该特征基于某个标记特征而受到约束.For the sake of this question assume it is impossible to modify 100 or 101.我已经知道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 {}
乍一看,这看起来很合理,但试图以通用的方式使用这种模式几乎是不可能的.例如,以通常微不足道的包装器 struct 扩展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
Conceptually we may be able to look at this and know that FooWrapper<F>: FooMarker<T>
implies F: FooMarker<T>
, but the compiler does not want to rely on this information. After thinking for a second, this kinda makes sense. Nowhere in impl Foo for FooWrapper
do we require that F: FooMarker<T>
.
How can I write 100 without rewriting 101 or 102?