我试图创建一个通用 struct ,它封装了isizeAtomicIsize,但当我试图为 struct 的两种可能实现实现实现一个trait时,我遇到了一个错误.我在下面创建了一个简单的例子来说明我的问题.

use std::sync::atomic::{AtomicIsize, Ordering};
use std::ops::Deref;
use std::marker::PhantomData;

pub trait Counted {
    fn inc(&self, value: isize);
}

pub type PlainCounter = isize;
pub type AtomicCounter = AtomicIsize;


pub struct Counter<'a, T: 'a> {
    counter: T,
    phantom: PhantomData<&'a T>,
}

impl<'a, T> Counter<'a, T>
    where T: Deref<Target = PlainCounter>
{
    pub fn new(counter: T) -> Self {
        Counter {
            counter: counter,
            phantom: PhantomData,
        }
    }
}

impl<'a, T> Counted for Counter<'a, T>
    where T: Deref<Target = PlainCounter>
{
    fn inc(&self, value: isize) {
        self.counter += 1;
    }
}

impl<'a, T> Counter<'a, T>
    where T: Deref<Target = AtomicCounter>
{
    pub fn new(counter: T) -> Self {
        Counter {
            counter: counter,
            phantom: PhantomData,
        }
    }
}

impl<'a, T> Counted for Counter<'a, T>
    where T: Deref<Target = AtomicCounter>
{
    fn inc(&self, value: isize) {
        self.counter.fetch_add(value, Ordering::SeqCst);
    }
}

(playground)

我得到的错误是编译器找到了conflicting implementations of trait `Counted` for type `Counter<'_, _>`.编译器似乎无法确定实现是针对两种不同的类型T,即T: Deref<Target = PlainCounter>T: Deref<Target = AtomicCounter>.是否有一种方法可以向编译器提供额外的信息,以便它能够区分这两种情况,还是我完全走错了路?

推荐答案

您可以通过定义第二个trait来完成这个模式,该trait执行实际的工作,并在(Counter<'a, T>, <T as Deref>::Target)秒内实现,然后让Counter trait调用该实现.

我不认为这很清楚,但我认为一个例子可以很好地说明这一点.为了清晰起见,使用Shepmaster的简短示例,我们将从以下内容开始:

use std::ops::Deref;

trait Foo {}

impl<T> Foo for T
    where T: Deref<Target = u8>
{}

impl<T> Foo for T
    where T: Deref<Target = bool>
{}

fn main() {}

为此:

use std::ops::Deref;

trait Foo {}
trait InnerFoo {}

impl<T> Foo for T
    where T: Deref,
          (T, <T as Deref>::Target): InnerFoo
{}

impl<T> InnerFoo for (T, u8)
{}

impl<T> InnerFoo for (T, bool)
{}

fn main() {}

Rust相关问答推荐

错误[E0793]具体何时发生:对打包字段的引用未对齐触发?

为什么在Rust struct 中只允许最后一个字段具有动态大小的类型

什么是谓词的简短和简洁类型

在rust中如何修改一个盒装函数并将其赋回?

关于如何初始化弱 struct 字段的语法问题

Rust类似功能是C++命名空间吗?

原始数组数据类型的默认trait实现

为什么铁 rust S似乎有内在的易变性?

使用Py03从Rust调用Python函数时的最佳返回类型

为什么不';t(&;mut-iter).take(n)取得iter的所有权?

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

一旦令牌作为文字使用,声明宏不匹配硬编码值?

Rust 中的 Option as_ref 和 as_deref 有什么不同

从 Axum IntoResponse 获取请求标头

我的 Axum 处理程序无法编译:未实现 IntoResponse 特征

为什么 no_std crate 可以依赖于使用 std 的 crate?

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的

如何创建动态创建值并向它们返回borrow 的工厂?

如果我立即等待,为什么 `tokio::spawn` 需要一个 `'static` 生命周期?

基于名称是否存在的条件编译