【问题标题】:Implement a trait for a generic trait为通用特征实现特征
【发布时间】:2021-01-09 18:41:51
【问题描述】:

在 Rust 中,如何为泛型 trait 实现 Trait?

trait One<S> {}

trait Two {}

// fails because S isn't contrained
impl<S, T> Two for T where T: One<S> {}

为了澄清,我正在尝试提供 BitAnd 特征 对于通用 Select 特征。

struct Thing<S> {
    field: S,
}

trait Select<S> {
    fn select(&self, thing: &Thing<S>) -> bool;
}

struct SelectUnion<S> (Box<dyn Select<S>>, Box<dyn Select<S>>);

// fails because S isn't contrained
impl<S, T> std::ops::BitAnd for T where T: Select<S> {
    type Output = SelectUnion<S>;

    fn bitand(self, rhs: Self) -> Self::Output {
        SelectUnion(Box::new(self), Box::new(rhs))
    }
}

【问题讨论】:

  • 你打算用这些特征做什么?如果您搜索该错误,则会有大量结果,但在这个问题中并没有太多问题。
  • 我假设 chrysn' 的答案仍然遵循,但您是否尝试过向 S 添加约束?即where S: MyTrait
  • @loganfsmyth 我已经澄清了这是要实现的目标。
  • @sam 我试过了,但仍然失败。 trait S 需要出现在正在实现的 trait 或“实现它的事物”中。

标签: rust


【解决方案1】:

不可能,原因是它会模棱两可。

想想这样的情况:

struct A;

impl One<u16> for A {}

impl One<u32> for A {}

Two 将基于两个 One 实现中的哪一个?两者都满足一揽子Two 实现的先决条件,但Two 对于任何类型都只能实现一次。就像您要提供两个单独的 impl Two for A 块一样。


在问题澄清后编辑:

以上内容仍然成立,但您可能想尝试是否可以将 Select 变成一个类型,可能通过将它变成一个可选择的包装器。

【讨论】:

  • 在我的补充说明中,意图更加明显。关键是在 Select (One) 特征上使用 BitAnd (Two) 并不关心 S 参数。所以从这个意义上说,错误是正确的; S 并不是真正的约束。但是,我不得不为Select (Two) 提及它。
  • 澄清没有太大变化。仅仅因为该特征碰巧不依赖于 S,编译器也无法证明这一点,也不是面向未来的。诚然,BitAnd 不太可能会开发出像 fn show_what_i_can_and_into() 这样的方法来执行类似 println!("{:?} can BitAnd with itself into {:?}", type_name_of(Self), type_name_of(Self::Output)) 的操作,但如果会的话,BitAnd::show_what_i_can_and_into() 会为 Select&lt;u16&gt;Select&lt;u32&gt; 做的事情呢?
猜你喜欢
  • 2019-12-08
  • 2021-11-14
  • 1970-01-01
  • 2015-08-07
  • 1970-01-01
  • 1970-01-01
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多