简体   繁体   English

在 Rust 的元组中传递多个引用

[英]Pass multiple references in a tuple in Rust

I have a trait with some associated type, and some of its functions take as input a reference of that type:我有一些关联类型的特征,它的一些函数将这种类型的引用作为输入:

trait Trait {
    type Value;

    fn do_something(&self, value: &Self::Value);
}

In one structure that implements this trait, Value is a tuple, because I need to pass multiple values to do_something :在实现此特征的一个结构中, Value是一个元组,因为我需要将多个值传递给do_something

struct Struct {}

impl Trait for Struct {
    type Value = (i64, String);

    fn do_something(&self, (a, b): &(i64, String)) {
        println!("{} {}", a, b);
    }
}

However, when I then use Struct in practice, I hit a wall.但是,当我在实践中使用Struct时,我碰壁了。 Either I do this:要么我这样做:

fn main() {
    let a = 10;
    let b = "foo".to_owned();
    let s = Struct {};

    s.do_something(&(a, b));  // This works...
    println!("{}", b);  // ...but the borrow checker complains here
}

but then I lose ownership of any non- Copy type in the tuple.但随后我失去了元组中任何非Copy类型的所有权。 Alternatively, I can do this:或者,我可以这样做:

fn main() {
    let a = 10;
    let b = "foo".to_owned();
    let s = Struct {};

    let t = (a, b);
    s.do_something(&t);
    let (a, b) = t;
    println!("{}", b);
}

which works, but the syntax is extremely heavy.这有效,但语法非常繁重。

Does anyone have some idea of how I can accomplish what I want in a more concise way?有谁知道我如何以更简洁的方式完成我想要的事情? I tried to have Struct::Value be of type (&i64, &String) , but then the borrow checker complains about needing a lifetime for those references, which I'd like to avoid if possible.我试图让Struct::Value的类型为(&i64, &String) ,但是借用检查器抱怨这些引用需要生命周期,如果可能的话,我想避免这种情况。

Another alternative I tried was to use a type parameter (so, Trait<Value> ) instead of an associated type.我尝试的另一种选择是使用类型参数(因此, Trait<Value> )而不是关联类型。 In that case, I can have Struct implement Trait<(&i64, &String)> without the lifetime issue I had with an associated type.在这种情况下,我可以让Struct实现Trait<(&i64, &String)> ,而不会出现关联类型的生命周期问题。 It works, but in my project it never makes sense for Struct to have more than one implementation of Trait , so I'd much prefer to use an associated type.它有效,但在我的项目中, Struct拥有多个Trait实现从来没有意义,所以我更喜欢使用关联类型。

Thanks for your time:-)谢谢你的时间:-)

I tried to have Struct::Value be of type (&i64, &String) , but then the borrow checker complains about needing a lifetime for those references, which I'd like to avoid if possible.我试图让Struct::Value的类型为(&i64, &String) ,但是借用检查器抱怨这些引用需要生命周期,如果可能的话,我想避免这种情况。

It's not possible to avoid lifetimes.不可能避免一生。 All references have lifetimes, some of which the compiler can infer for you and some of which you have to explicitly annotate yourself.所有引用都有生命周期,其中一些是编译器可以为你推断的,而其中一些你必须自己显式地注释。 Note: the compiler isn't always right so sometimes you have to explicitly annotate lifetimes anyway despite the compiler's inferences.注意:编译器并不总是正确的,所以有时尽管编译器的推论,你还是必须显式地注释生命周期。

In that case, I can have Struct implement Trait<(&i64, &String)> without the lifetime issue I had with an associated type.在这种情况下,我可以让Struct实现Trait<(&i64, &String)> ,而不会出现关联类型的生命周期问题。

Right, because the lifetimes the compiler inferred for those references happened to work, but you shouldn't be afraid of explicitly annotating them yourself when you need to.是的,因为编译器为这些引用推断出的生命周期恰好可以工作,但是您不应该害怕在需要时自己显式注释它们。

It works, but in my project it never makes sense for Struct to have more than one implementation of Trait , so I'd much prefer to use an associated type.它有效,但在我的项目中, Struct拥有多个Trait实现从来没有意义,所以我更喜欢使用关联类型。

Alright then let's use an associated type.好吧,让我们使用关联类型。 Here's the code with all the necessary lifetime annotations:这是包含所有必要生命周期注释的代码:

trait Trait<'a> {
    type Value;

    fn do_something(&self, value: Self::Value);
}

struct Struct {}

impl<'a> Trait<'a> for Struct {
    type Value = (&'a i64, &'a String);

    fn do_something(&self, (a, b): Self::Value) {
        println!("{} {}", a, b);
    }
}

fn main() {
    let a = 10;
    let b = "foo".to_owned();
    let s = Struct {};

    s.do_something((&a, &b)); // compiles
    println!("{}", b); // compiles
}

playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM