Function 有没有办法避免与trait对象解除引用?

Function 有没有办法避免与trait对象解除引用?,function,parameters,rust,traits,dereference,Function,Parameters,Rust,Traits,Dereference,我遇到了一个问题,我认为使用trait对象来解决这个问题是完美的。虽然我设法使它工作,但它看起来比它应该的复杂得多,所以我想知道是否有一种更优化的方法来使用trait对象 示例代码: /* This takes a slice of objects implementing trait and compares each of them with all other objects in the slice, if they interact with each other both ob

我遇到了一个问题,我认为使用trait对象来解决这个问题是完美的。虽然我设法使它工作,但它看起来比它应该的复杂得多,所以我想知道是否有一种更优化的方法来使用trait对象

示例代码:

/* This takes a slice of objects implementing trait and compares each of 
 them with all other objects in the slice, if they interact with each other
 both objects should call a certain function with the other object as a parameter.

 This is used for a collision system, in case you know of a better way to solve this please
 let me know. */

fn foo(objects: &mut [Box<Trait>]) {
    let mut active_objects: Vec<&mut Box<Trait>> = vec!();

    for current in objects.iter_mut() {
        for other in active_objects.iter_mut() {
            if (**current).is_interacting(&***other) {
                current.boo(&mut ***other);
                other.boo(&mut **current);
            }
        }

        active_objects.push(current);
    }
}

trait Trait {
    fn boo(&mut self, other: &mut Trait);

    fn is_interacting(&self, other: & Trait) -> bool;
}
/*这将获取实现trait的对象片段,并比较每个对象
它们与切片中的所有其他对象(如果它们彼此交互)
两个对象都应该调用某个函数,另一个对象作为参数。
这是用于碰撞系统,如果您知道更好的解决方法,请
让我知道*/
fn foo(对象:&mut[Box]){
让多个活动对象:Vec=Vec!();
用于对象中的电流。iter_mut(){
对于其他处于活动状态的对象。iter_mut(){
如果(**当前)。是否相互作用(&***其他){
当前。boo(&mut***其他);
其他。boo(&mut**current);
}
}
活动对象推送(当前);
}
}
特质{
fn boo(&mut self,other:&mut Trait);
fn是互动的(自我、他人和特质)->bool;
}
有没有一种方法可以让我在每次使用实际对象时不必编写类似于
&***
的东西

if(**current).is_interacting(&***other)
变为
if current.is_interacting(&***other)
在这种情况下,Rust会自动解除引用。

as,
as_mut()
可以对
框进行可变引用,这提供了更好的解决方案:

fn foo(objects: &mut [Box<Trait>]) {
    let mut active_objects: Vec<&mut Box<Trait>> = vec!();

    for current in objects.iter_mut() {
        for other in active_objects.iter_mut() {
            let current = current.as_mut();
            let other = other.as_mut();

            if current.is_interacting(other) {
                current.boo(other);
                other.boo(current);
            }
        }

        active_objects.push(current);
    }
}

trait Trait {
    fn boo(&mut self, other: &mut Trait);

    fn is_interacting(&self, other: &Trait) -> bool;
}
fn foo(对象:&mut[Box]){
让多个活动对象:Vec=Vec!();
用于对象中的电流。iter_mut(){
对于其他处于活动状态的对象。iter_mut(){
设current=current.as_mut();
让other=other.as_mut();
如果当前。_正在交互(其他){
目前,boo(其他);
其他。boo(当前);
}
}
活动对象推送(当前);
}
}
特质{
fn boo(&mut self,other:&mut Trait);
fn是互动的(自我、他人和特质)->bool;
}

无需在
活动对象
向量中保留对
对象的引用。这将起作用,并消除大部分解引用:

fn foo(对象:&mut[Box]){
让多个活动对象:Vec=Vec!();
用于对象中的电流。iter_mut(){
设current=current.as_mut();
对于其他处于活动状态的对象。iter_mut(){
如果当前。_正在交互(*其他){
当前。boo(*其他);
其他。boo(当前);
}
}
活动对象推送(当前);
}
}

您可以删除代码中的所有取消引用:

fn foo(objects: &mut [Box<Trait>]) {
    let mut active_objects: Vec<&mut Box<Trait>> = vec![];

    for current in objects.iter_mut() {
        for other in active_objects.iter_mut() {
            if current.is_interacting(other) {
                current.boo(other);
                other.boo(current);
            }
        }

        active_objects.push(current);
    }
}
fn foo(对象:&mut[Box]){
让多个活动对象:Vec=Vec![];
用于对象中的电流。iter_mut(){
对于其他处于活动状态的对象。iter_mut(){
如果当前。_正在交互(其他){
目前,boo(其他);
其他。boo(当前);
}
}
活动对象推送(当前);
}
}
您可以通过以下方式启用此功能:

impl bool{
(**self.is_交互(其他)
}
}
盒子的impl特性
哪里
T:性状+?大小,
{
fn boo(&mut self,其他:&mut Trait){
(**self.boo(其他)
}
fn是互动的(自我、他人和特质)->bool{
(**self.is_交互(其他)
}
}

这是一段一次性代码,您可以在特征定义附近添加它,从而使调用站点更干净。

您不需要取消引用当前的
,它是自动的。@Boiethios谢谢:),这将我从10
*
增加到8。这是一个开始。
other
上有问题,因为类型是
&mut&mut std::boxed::Box
。是的,这是真的。但我没有找到防止这种情况发生的方法,因为
active_objects
必须是一个引用向量,否则我会跳出借来的上下文,我必须
iter_mut
才能变异traitobject,因此,虽然我同意
&mut&mut
是不可取的,但我不知道如何做,否则……你可以问这样一个问题:“如何可变地访问向量中的所有对?”。我会朝着这个方向去寻找:或者是一个很好的解决方案,但我相信有一个更简单的解决方案可以满足OP的需求这只是进一步的一步
let current=current.as_mut()也有效。我不确定它是否会更简单。它看起来肯定比我的第一次测试要好,我做了一些测试,它实际上比我原来的函数快了大约4%,这是我最想不到的。如果没有更好的答案,我会接受你的。谢谢
as_mut
borrow_mut
似乎根本不会影响处理速度,因此使用
as_mut
应该更干净,因为我不必使用任何东西。很好,但是值得记住的是,
&mut Trait
是一个胖指针,占用的空间是
&mut Box
的两倍。但这意味着它使用较少的间接寻址,因此可以提供更快的访问速度。与两个答案的速度相比,这一个比其他函数快10%到15%,这是令人印象深刻的最佳解决方案!Thanks@ViktorChv阿塔尔,对,但和往常一样,坐板凳比较好。内存访问次数的减少可能会被缓存压力的增加所抵消。谢谢,我不知道可以在
&
上使用
impl
impl<'a, T> Trait for &'a mut T
where
    T: Trait + ?Sized,
{
    fn boo(&mut self, other: &mut Trait) {
        (**self).boo(other)
    }

    fn is_interacting(&self, other: &Trait) -> bool {
        (**self).is_interacting(other)
    }
}

impl<T> Trait for Box<T>
where
    T: Trait + ?Sized,
{
    fn boo(&mut self, other: &mut Trait) {
        (**self).boo(other)
    }

    fn is_interacting(&self, other: &Trait) -> bool {
        (**self).is_interacting(other)
    }
}