【问题标题】:How to implement a trait function generic over return type [duplicate]如何在返回类型上实现通用的特征函数[重复]
【发布时间】:2021-06-21 20:27:14
【问题描述】:
trait CallOnceSafe {
    fn call_once_safe<R>(&mut self, x: &mut [u8]) -> smoltcp::Result<R>;
}

impl<R, F: FnOnce(&mut [u8]) -> smoltcp::Result<R>> CallOnceSafe for Option<F> {
    fn call_once_safe<R>(&mut self, x: &mut [u8]) -> smoltcp::Result<R> {
        // panics if called more than once - but A::consume() calls it
        // only once
        let func = self.take().unwrap();
        func(x)
    }
}

在这种情况下,我不能使用 fn call_once_safe&lt;R&gt;,因为 R 已经被用作实现 tair 的类型参数。

如何使用泛型类型 R 实现这个 trait 函数?

【问题讨论】:

标签: rust


【解决方案1】:

由于现在定义了CallOnceSafecall_once_safe的调用者可以选择R,而实现者必须保证无论选择什么Rsmoltcp::Result&lt;R&gt;将被返回,但是 Option&lt;F&gt; 的任何实现,其中 F: FnOnce(&amp;mut [u8]) -&gt; smoltcp::Result&lt;R&gt; 仅适用于 F 可以返回的特定 R

唯一合理的解决方案是更改CallOnceSafe 的定义方式。有两种方法可以做到这一点:

  • 使R 成为泛型类型参数。这将允许您选择要为哪个R 实施CallOnceSafe&lt;R&gt;
trait CallOnceSafe<R> {
    fn call_once_safe(&mut self, x: &mut [u8]) -> smoltcp::Result<R>;
}

impl<R, F: FnOnce(&mut [u8]) -> smoltcp::Result<R>> CallOnceSafe<R> for Option<F> {
    fn call_once_safe(&mut self, x: &mut [u8]) -> smoltcp::Result<R> {
        // panics if called more than once - but A::consume() calls it
        // only once
        let func = self.take().unwrap();
        func(x)
    }
}
  • R 设为关联类型。这是可行的,因为实现者选择了关联的类型。请注意,我选择将其命名为Ret,因为使用R 会导致type R = R;,我认为这有点令人困惑(但仍然是完全有效的代码)。
trait CallOnceSafe {
    type Ret;
    fn call_once_safe(&mut self, x: &mut [u8]) -> smoltcp::Result<Self::Ret>;
}

impl<R, F: FnOnce(&mut [u8]) -> smoltcp::Result<R>> CallOnceSafe for Option<F> {
    type Ret = R;
    fn call_once_safe(&mut self, x: &mut [u8]) -> smoltcp::Result<R> {
        // panics if called more than once - but A::consume() calls it
        // only once
        let func = self.take().unwrap();
        func(x)
    }
}

两种解决方案的区别在于,泛型类型参数将允许同一类型多次实现 trait,每次使用不同的R,而关联类型只允许一个 impl 用于每种类型。如果您只打算为 Option&lt;F&gt; 实现它并使用它来减少代码重复,这应该无关紧要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 2015-01-12
    • 2020-05-20
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 2013-06-25
    相关资源
    最近更新 更多