繁体   English   中英

向量的不同内容上的特征实现冲突

[英]conflicting implementation for a trait on different contents of a vector

我有一个特质

pub trait Reducer {
  type Item;
  fn reduce_all(&self) -> Self::Item
}

我有一个具体的类型

struct Counter {
  amount: u32
}

我已经为Vec<Counter>实现了Reducer ,如下所示:

impl<T: Borrow<Counter>> Reducer for Vec<T> {
  type Item::Counter;
  fn reduce_all(&self) -> Self::Item { ... implementation here ...}
}

现在我有不同的具体类型

struct Statistic {
  x_val: u32
}

并尝试使用相同的技术在 Vec 上实现 Reducer:

impl<T: Borrow<SessionStat>> Reducer for Vec<T> {
...

但收到此错误:

impl<T: Borrow<Counter>> Reducer for Vec<T> {
   | ------------------------------------------- first implementation here
...
67 | impl<T: Borrow<SessionStat>> Reducer for Vec<T> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `std::vec::Vec<_>`

不确定如何针对不同的向量内容两次实现此特征

根据您的情况,您可能不希望Item成为关联类型,而是让您的Reducer特征对其返回的类型具有通用性。 这将允许您将集合“简化”为多种类型,而不仅仅是一种类型,并且根据集合的类型及其应该减少的内容它可以消除使用哪个实现的歧义。 C.f. 这本书这个答案关于通用特征和相关类型之间的区别。

您的实现可能看起来像这样:

use std::borrow::Borrow;

pub trait Reducer<I> {
    // ----------^^^
    // make `Reducer` generic over the type it returns
    // ---------------------v
    fn reduce_all(&self) -> I;
}

struct Counter {
    amount: u32,
}

impl<T: Borrow<Counter>> Reducer<Counter> for Vec<T> {
    fn reduce_all(&self) -> Counter {
        todo!()
    }
}

struct SessionStat {
    x_val: u32,
}

impl<T: Borrow<SessionStat>> Reducer<SessionStat> for Vec<T> {
    fn reduce_all(&self) -> SessionStat {
        todo!()
    }
}

操场

因为你的 trait 不是通用的,所以你只能实现一次。 如果要实现 trait 多类型,则必须使其成为通用类型。 问题是您使用关联类型,因此您必须摆脱它并使您的 trait 像这样:

pub trait Reducer<T> {
  fn reduce_all(&self) -> T
}

那么你可以做

impl<T: Borrow<Counter>> Reducer<Counter> for Vec<T> {
  fn reduce_all(&self) -> Counter { ... implementation here ...}
}

impl<T: Borrow<SessionStat>> Reducer<SessionStat> for Vec<T> {
...
}

编辑:

看着它,您有可能通过创建一个新特征并执行以下操作来保持该特征的原始方式:

您创建一个将类型标记为可简化的特征:

pub trait Reducible {
  fn foo(self, &mut Self); 
// reduce self into another self, or whatever you are doing
// you get the point
}

然后只为 Vec 实现一次特征:

impl<T: Reducible, B: Borrow<T>> Reducer for Vec<B> {
  type Item = T; // you then now keep the associated type !
  fn reduce_all(&self) -> T { ... implementation here ...}
}

所以这种方式是 Reducible 特性完成了大部分工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM