Есть ли способ в общих чертах реализовать черту для объектов в умных указателях? - PullRequest
1 голос
/ 11 июня 2019

Есть ли способ обеспечить реализацию для черты объектов в интеллектуальных указателях (например, Box, Rc и т. Д.)?

Пример:

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. Можно ли это решить с помощью связанного типа?

1 Ответ

1 голос
/ 12 июня 2019
      /-- everything here
impl<Types...>     Trait              for         Self
                     \-- has to appear here         \-- or here

Как говорится в сообщении об ошибке , Types... должен быть ограничен Trait, Self или предикатами Trait или 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())
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...