generics - 有没有办法为智能指针中的对象通用地实现一个特征?

标签 generics rust traits

有没有一种方法可以通用地为智能指针中的对象(例如 BoxRc 等)的特征提供实现?

例子:

use std::borrow::Borrow;
use std::rc::Rc;

trait KindaEqual<Rhs = Self> {
    fn kinda_equal(&self, other: &Rhs) -> bool;
}

// Nice to have (still need to copy-paste for each LHS container)
impl<T, Rhs, WrappedRhs> KindaEqual<WrappedRhs> for T
where
    WrappedRhs: Borrow<Rhs>,
    T: KindaEqual<Rhs>,
{
    fn kinda_equal(&self, other: &WrappedRhs) -> bool {
        self.kinda_equal(other.borrow())
    }
}

// Best to have (handles both LHS and RHS containers)
impl<WrappedT, T, Rhs, WrappedRhs> KindaEqual<WrappedRhs> for WrappedT
where
    WrappedRhs: Borrow<Rhs>,
    WrappedT: Borrow<T>,
    T: KindaEqual<Rhs>,
{
    fn kinda_equal(&self, other: &WrappedRhs) -> bool {
        self.borrow().kinda_equal(other.borrow())
    }
}

impl KindaEqual for f64 {
    fn kinda_equal(&self, other: &Self) -> bool {
        num::abs(self - other) < 0.01f64
    }
}

impl KindaEqual<u64> for f64 {
    fn kinda_equal(&self, other: &u64) -> bool {
        num::abs(self - *other as f64) < 1f64
    }
}

fn main() {
    assert!(3.141592654.kinda_equal(&3.14));
    assert!(3.141592654.kinda_equal(&3));
    assert!(3.141592654.kinda_equal(&Rc::new(3.14)));
}

上面给出了错误:

error[E0207]: the type parameter `Rhs` is not constrained by the impl trait, self type, or predicates
 --> src/main.rs:9:9
  |
9 | impl<T, Rhs, WrappedRhs> KindaEqual<WrappedRhs> for T
  |         ^^^ unconstrained type parameter

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
  --> src/main.rs:20:16
   |
20 | impl<WrappedT, T, Rhs, WrappedRhs> KindaEqual<WrappedRhs> for WrappedT
   |                ^ unconstrained type parameter

error[E0207]: the type parameter `Rhs` is not constrained by the impl trait, self type, or predicates
  --> src/main.rs:20:19
   |
20 | impl<WrappedT, T, Rhs, WrappedRhs> KindaEqual<WrappedRhs> for WrappedT
   |                   ^^^ unconstrained type parameter

我读到过添加关联类型可能会修复它,但这是不可取的,因为它会强制使用特征来实现它。

  1. 这可以在没有关联类型的情况下解决吗? (最好)
  2. 这可以用关联类型解决吗?

最佳答案

      /-- everything here
impl<Types...>     Trait              for         Self
                     \-- has to appear here         \-- or here

作为error message表示,Types... 必须受到 TraitSelfTrait self

如果您可以为每个 LHS 容器复制粘贴,您可以将 Borrow 处理向下移动到函数本身,如下所示:

use std::borrow::Borrow;

trait KindaEqual<Rhs = Self> {
    fn kinda_equal<R: Borrow<Rhs>>(&self, other: &R) -> bool;
}

impl KindaEqual<u32> for u32 {
    fn kinda_equal<R: Borrow<u32>>(&self, other: &R) -> bool {
        self == other.borrow()
    }
}

// repeat for all supported containers
impl<T> KindaEqual<T> for Box<T>
where
    T: KindaEqual<T>,
{
    fn kinda_equal<R: Borrow<T>>(&self, other: &R) -> bool {
        (&**self).kinda_equal(other.borrow())
    }
}

关于generics - 有没有办法为智能指针中的对象通用地实现一个特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56537015/

相关文章:

java - 破译泛型语法

c# - 将泛型类型声明为接口(interface)的属性?

c# - 将通用类绑定(bind)到特定接口(interface)

rust - 我将如何在 Rust 中创建和使用字符串来字符串化 Hashmap?

PHP:类中的特征与其他特征冲突

java - 假设以下是类 : public <T Implement comparable <T>> tT greatest(T arg1, arg2 中的方法头)

rust - 这个作用域线程代码可以更改为使用 `FnOnce()` 而不是 `Box<FnOnce()>` 吗?

rust - 如何从方法返回特征的实例?

python - 带有文件对话框的样式表

python - 使用适配器时如何在 TraitsUI TreeView 中启用右键单击菜单?