13 votes

Comment vérifier si deux variables de référence empruntent le même objet ?

J'ai une structure qui stocke toutes les références en lecture seule, par exemple :

struct Pt { x : f32, y : f32, }
struct Tr<'a> { a : &'a Pt }

Je veux impl Eq para Tr pour vérifier si la sous-couche a référence à exactement la même Pt :

let trBase1 = Pt::new(0.0, 0.0);
let trBase2 = Pt::new(0.0, 0.0);
assert!(trBase1 == trBase2);        // ok.
let tr1 = Tr::new(&trBase1);
let tr2 = Tr::new(&trBase2);
let tr3 = Tr::new(&trBase1);
assert!(tr1 == tr3);                // ok.
assert!(tr1.a == te2.a);            // ok. Using Eq for Pt that compare values.
assert!(tr1 != tr2);                // panicked! Not intended.

donc maintenant j'ai

impl<'a> PartialEq for Tr<'a> {
    fn eq(&self, v : &Tr<'a>) -> bool {
        // self.a == v.a // doesn't work.
    }
}

qu'est-ce que je dois écrire ?

12voto

SCappella Points 7821

Vous pouvez utiliser std::ptr::eq pour comparer les adresses de deux pointeurs. Références ( &T o &mut T ) sera automatiquement converti en pointeur sous-jacent ( *const T ) si cette fonction est alimentée. Bien sûr, il n'est pas logique qu'une référence mutable ait la même adresse qu'une autre référence, puisque les références mutables sont toujours des références exclusives. *const T .

// This derive will use the equality of the underlying fields
#[derive(PartialEq)]
struct Pt {
    x: f32,
    y: f32,
}

impl Pt {
    fn new(x: f32, y: f32) -> Self {
        Self { x, y }
    }
}

struct Tr<'a> {
    a: &'a Pt,
}

impl<'a> Tr<'a> {
    fn new(a: &'a Pt) -> Self {
        Self { a }
    }
}

// Here we use std::ptr::eq to compare the *addresses* of `self.a` and `other.a`
impl<'a> PartialEq for Tr<'a> {
    fn eq(&self, other: &Tr<'a>) -> bool {
        std::ptr::eq(self.a, other.a)
    }
}

fn main() {
    let tr_base1 = Pt::new(0.0, 0.0);
    let tr_base2 = Pt::new(0.0, 0.0);
    assert!(tr_base1 == tr_base2);

    let tr1 = Tr::new(&tr_base1);
    let tr2 = Tr::new(&tr_base2);
    let tr3 = Tr::new(&tr_base1);

    assert!(tr1 == tr3);
    assert!(tr1.a == tr2.a);
    assert!(tr1 != tr2);
}

(lien vers le terrain de jeu)

3voto

Francis Gagné Points 708

Transformez les références en pointeurs bruts et comparez-les.

impl<'a> PartialEq for Tr<'a> {
    fn eq(&self, v: &Tr<'a>) -> bool {
        self.a as *const _ == v.a as *const _
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X