特性オブジェクト間の等価性をテストするにはどうすればいいですか? 質問する

特性オブジェクト間の等価性をテストするにはどうすればいいですか? 質問する

編集者注: このコード例は Rust 1.0 より前のバージョンのものであり、構文的に有効な Rust 1.0 コードではありません。このコードの更新バージョンでは異なるエラーが発生しますが、回答には依然として貴重な情報が含まれています。

次のケースでは、等価性をテストできないようです。これはなぜでしょうか? 回避策はありますか? (私は Rust 0.11 を使用しています)。

trait A: PartialEq {}

#[deriving(PartialEq)]
enum T {Ta, Tb}

impl A for T {}

fn main() {
  assert!(Ta == Ta);
  assert!(Ta != Tb);
  assert!(some_fn(&Ta, &Ta));
  assert!(!some_fn(&Ta, &Tb));
}

fn some_fn(an_a: &A, another_a: &A) -> bool {
    an_a == another_a
// ERROR ^~~~~~~~~~~~ binary operation `==` cannot be applied to type `&A`
}

fn another_fn(an_a: &A + PartialEq, another_a: &A + PartialEq) -> bool {
               // ERROR: ^~~~~~~~~ only the builtin traits can be used as closure or object bounds
    an_a == another_a
}

ベストアンサー1

ウラジミール・マトヴェエフの助けAny、私は、を使用して特性を具体的な型にダウンキャストし、結果の値の等価性をテストする方法を見つけました。

// `Any` allows us to do dynamic typecasting.
use std::any::Any;

trait A {
    // An &Any can be cast to a reference to a concrete type.
    fn as_any(&self) -> &dyn Any;

    // Perform the test.
    fn equals_a(&self, _: &dyn A) -> bool;
}

#[derive(Debug, PartialEq)]
enum T {
    Ta,
    Tb,
}

// Implement A for all 'static types implementing PartialEq.
impl<S: 'static + PartialEq> A for S {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn equals_a(&self, other: &dyn A) -> bool {
        // Do a type-safe casting. If the types are different,
        // return false, otherwise test the values for equality.
        other
            .as_any()
            .downcast_ref::<S>()
            .map_or(false, |a| self == a)
    }
}

fn main() {
    assert_eq!(T::Ta, T::Ta);
    assert_ne!(T::Ta, T::Tb);
    assert!(some_fn(&T::Ta, &T::Ta));
    assert!(!some_fn(&T::Ta, &T::Tb));
}

fn some_fn(an_a: &dyn A, another_a: &dyn A) -> bool {
    // It works!
    an_a.equals_a(another_a)
}

おすすめ記事