Reference 如何实现结构引用的addtrait?

Reference 如何实现结构引用的addtrait?,reference,rust,traits,lifetime,Reference,Rust,Traits,Lifetime,我制作了一个两元素的向量结构,我想重载+操作符 我让我所有的函数和方法都采用引用,而不是值,并且我希望+操作符以同样的方式工作 impl Add for Vector { fn add(&self, other: &Vector) -> Vector { Vector { x: self.x + other.x, y: self.y + other.y, } } } 根据我尝试

我制作了一个两元素的
向量
结构,我想重载
+
操作符

我让我所有的函数和方法都采用引用,而不是值,并且我希望
+
操作符以同样的方式工作

impl Add for Vector {
    fn add(&self, other: &Vector) -> Vector {
        Vector {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}
根据我尝试的变体,我会遇到生存期问题或类型不匹配。具体来说,
&self
参数似乎没有被视为正确的类型

我在
impl
Add
上看到了带有模板参数的示例,但它们只会导致不同的错误

我发现答案中的代码不起作用,即使我使用std::ops::Mul在顶部

我每晚都在使用rustc 1.0.0(ed530d7a3 2015-01-16 22:41:16+0000)


我不会接受“你只有两个字段,为什么要使用引用”作为答案;如果我想要一个100元素的结构呢?我会接受这样一个答案,即即使是大型结构,我也应该按值传递,如果是这样的话(我不认为是这样)。我有兴趣了解结构大小和按值传递与结构传递的经验法则,但这不是当前的问题。

您需要在
&Vector
上实现
Add
,而不是在
Vector
上实现

impl<'a, 'b> Add<&'b Vector> for &'a Vector {
    type Output = Vector;

    fn add(self, other: &'b Vector) -> Vector {
        Vector {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}

impl Add如果要支持所有场景,必须支持所有组合:

  • &托普大学
  • 托普大学
  • &托普大学
  • 托普大学
在生锈的地方

幸运的是,有一个rust板条箱,它还提供了一个宏来为我们编写样板文件:板条箱提供了宏,它生成所有的组合

这是他们的样本:

#[宏使用]外部板条箱执行;
使用std::ops;
执行!(+|a:&DonkeyKong,b:&DonkeyKong |->i32{a.bananas+b.bananas});
fn main(){
让total_香蕉=&DonkeyKong::new(2)+&DonkeyKong::new(4);
断言(6,总数量);
让total_香蕉=&DonkeyKong::new(2)+DonkeyKong::new(4);
断言(6,总数量);
让total_香蕉=DonkeyKong::new(2)+&DonkeyKong::new(4);
断言(6,总数量);
让total_香蕉=DonkeyKong::new(2)+DonkeyKong::new(4);
断言(6,总数量);
}

更好的是,如果运算符恰好是可交换的,它们还将生成参数颠倒的运算符。

“Add::Add总是按值获取self。这里,self是一种向量类型,因为这是我们正在实现的Add-on类型。”这是关键信息,自我类型的变化取决于该特质是否作为参考。谢谢哇!令人惊讶的是,这是正确的答案,但事实确实如此。这一切都让人感觉很不直观。你可以用两种不同的方式定义Add,这取决于它是否是一个引用,这感觉像是一个麻烦。要在@Squirrel的评论中反弹,我们应该实现一个操作来避免冗余吗?“按引用添加”复制值并应用“按值添加”,或“按值添加”对移动的值应用“按引用添加”?是的,绝对正确!代码重用总是好的!:)通常,如果克隆/复制值比较便宜,则希望按值实现为主,否则希望按引用实现。实际上,如果一个是ref,另一个不是ref,则需要实现所有组合,反之亦然。在rust中,它是通过宏来完成的。。。“如果我想要一个100元素的结构该怎么办”-Rust使用了一些优化,比如RVO,在适当的时候会自动使用一个引用,这是更好的选择。@Shepmaster:RVO只会影响返回值,我是按值返回的。你能指出任何表明大型结构的特性应该通过值来实现的文档吗?我所知道的最好的文档是。但是,我检查了生成的LLVM(略微清理):
(%struct.Big*sret,%struct.Big*,%struct.Big*)
。我并不自称是LLVM专家,但这看起来像是通过引用自动获取和返回。文档还引用了返回值,我同意返回值不应该是ref。事实上,文档曾经说过,除非需要,否则不应该使用指针作为输入参数,但实际上已经删除了。此外,我还将您的示例更改为按引用传递,发现它删除了两个分配(
%arg7=alloca%struct.Big,align 8
%arg8=alloca%struct.Big,align 8
),所以看起来对于大型结构,至少引用更好。我应该指出,我对LLVM的了解比任何人都少,所以我的解释可能完全是湿的。使用引用进行运算符重载的另一个明显缺点是,如果碰巧没有引用,
让c=(&a)+(&b)很烦人。