Rust 仅当对象是从同一父对象创建时,如何比较它们?

Rust 仅当对象是从同一父对象创建时,如何比较它们?,rust,Rust,我只想比较Objs,当它们是从同一父对象创建的,并且有效,但只有一种方法:如果切换比较顺序,则无效 以下是最简单的代码: use std::marker::PhantomData; struct Parent { val: u64, } impl Parent { pub fn new(v: u64) -> Parent { Parent { val: v } } pub fn child(&self, v: u64) ->

我只想比较
Obj
s,当它们是从同一
父对象创建的,并且有效,但只有一种方法:如果切换比较顺序,则无效

以下是最简单的代码:

use std::marker::PhantomData;

struct Parent {
    val: u64,
}

impl Parent {
    pub fn new(v: u64) -> Parent {
        Parent { val: v }
    }

    pub fn child(&self, v: u64) -> Child {
        Child {
            val: v,
            phantom: PhantomData,
        }
    }
}

struct Child<'a> {
    val: u64,
    phantom: PhantomData<&'a Parent>,
}

impl<'a> Child<'a> {
    pub fn compare(&'a self, l: &Obj<'a>, r: &Obj<'a>) -> bool {
        l.val == r.val
    }

    pub fn obj(&'a self, v: u64) -> Obj<'a> {
        Obj {
            val: v,
            child: self,
        }
    }
}

struct Obj<'a> {
    val: u64,
    child: &'a Child<'a>,
}

impl<'a> PartialEq<Obj<'a>> for Obj<'a> {
    fn eq(&self, other: &Obj<'a>) -> bool {
        self.child.compare(self, other)
    }
}

#[test]
fn test() {
    let parent = Parent::new(1);
    let child = parent.child(2);
    let obj1 = child.obj(3);
    let obj2 = child.obj(3);

    // those are from the same parent, this sould work (and works).
    assert!(obj1 == obj2);
    assert!(obj2 == obj1);

    let parent2 = Parent::new(1);
    let child2 = parent2.child(2);
    let obj12 = child2.obj(3);
    let obj22 = child2.obj(3);

    // this works fine too
    assert!(obj12 == obj22);
    assert!(obj22 == obj12);

    // those are from different parents

    //assert!(obj1 == obj12); // that line DOES NOT compile, which is exactly what I want!
    assert!(obj12 == obj1); // but that line suddenly DOES compile.
}
使用std::marker::PhantomData;
结构父级{
瓦尔:u64,
}
内隐父代{
发布fn新版本(v:u64)->父版本{
父{val:v}
}
发布fn child(&self,v:u64)->child{
孩子{
瓦尔:v,
幻影:幻影数据,
}
}
}
结构孩子,
}
恳求{
pub fn compare(&'a self,l:&Obj)->bool{
l、 val==r.val
}
pub fn obj(&'a self,v:u64)->obj{
瓦尔:u64,
孩子:&'a child PartialEq{

fn eq(&self,other:&Obj我很乐意解释终身方法,但它似乎不可行


X
Y
的一个子类型时(表示为
X这里有一个可能会让你兴奋或吓死你的答案:使用单子

特别是。不幸的是,我无法向您解释,但我的理解是,在这种情况下,它可能会很有用。如果您找到答案,请告诉我们

有人向我展示了这一点:

您可以复制不变式生命周期,这实际上是在中完成的。我之所以说它非常重要,是因为使其属性有用的唯一方法是要求在闭包中创建(或至少访问)每个文档

实用的解决方案是不尝试产生这些编译时错误,而只是在比较中包含父指针:

#[derive(Debug,Copy,Clone,PartialEq)]
struct Parent {
    val: u64,
}

impl Parent {
    fn child(&self) -> Child { Child { parent: self, val: self.val } }
}

#[derive(Debug,Copy,Clone)]
struct Child<'a> {
    parent: &'a Parent,
    val: u64,
}

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

fn main() {
    let (p1, p2) = (Parent { val: 42 }, Parent { val: 42 });
    let p1_c1 = p1.child();
    let p1_c2 = p1.child();
    let p2_c1 = p2.child();

    println!("{}", p1_c1 == p1_c2);
    println!("{}", p1_c1 == p2_c1);
}
#[派生(调试、复制、克隆、部分Q)]
结构父级{
瓦尔:u64,
}
内隐父代{
fn child(&self)->child{child{parent:self,val:self.val}
}
#[派生(调试、复制、克隆)]
结构子对象{

fn均衡器(&self,other:&child)我不认为生命周期是正确的编码方式。因为第二个父对象是在第一个父对象之后定义的,所以它的生命周期严格地在第一个父对象的生命周期内。您可以想到的任何生命周期检查都将允许任何具有第二个生命周期的对象在fir的某些情况下使用st lifetime是必需的。这说明使用lifetime不是解决此问题的可行方法吗?如果是,您可能希望明确声明。我不知道,但这还不够。这个答案只是一个过长的注释:)@bluss:我记得我曾经玩弄过这个,nmatsakis警告过我不要试图滥用生命周期作为品牌:Rust语言无法保证它的生命周期推断是向后兼容的;今天的双亲已经可以用相同的生命周期创造出来,这意味着我们很幸运,这个计划现在失败了,而不是失败了很好,这是一些关于生命周期的额外信息。注意我提到的
不变量生命周期>
#[derive(Debug,Copy,Clone,PartialEq)]
struct Parent {
    val: u64,
}

impl Parent {
    fn child(&self) -> Child { Child { parent: self, val: self.val } }
}

#[derive(Debug,Copy,Clone)]
struct Child<'a> {
    parent: &'a Parent,
    val: u64,
}

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

fn main() {
    let (p1, p2) = (Parent { val: 42 }, Parent { val: 42 });
    let p1_c1 = p1.child();
    let p1_c2 = p1.child();
    let p2_c1 = p2.child();

    println!("{}", p1_c1 == p1_c2);
    println!("{}", p1_c1 == p2_c1);
}