在 Rust 的元组中传递多个引用
Pass multiple references in a tuple in Rust
我有一些关联类型的特征,它的一些函数将这种类型的引用作为输入:
trait Trait {
type Value;
fn do_something(&self, value: &Self::Value);
}
在实现这个特性的一个结构中,Value
是一个元组,因为我需要将多个值传递给do_something
:
struct Struct {}
impl Trait for Struct {
type Value = (i64, String);
fn do_something(&self, (a, b): &(i64, String)) {
println!("{} {}", a, b);
}
}
然而,当我在实践中使用Struct
时,我碰壁了。要么我这样做:
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
}
但随后我失去了元组中任何非 Copy
类型的所有权。或者,我可以这样做:
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);
}
有效,但语法非常繁重。
有没有人知道如何以更简洁的方式完成我想要的?我试图让 Struct::Value
成为 (&i64, &String)
类型,但随后借用检查器抱怨这些引用需要生命周期,我希望尽可能避免这种情况。
我尝试的另一种选择是使用类型参数(因此,Trait<Value>
)而不是关联类型。在这种情况下,我可以让 Struct
实现 Trait<(&i64, &String)>
而不会出现关联类型的生命周期问题。它有效,但在我的项目中,Struct
有多个 Trait
的实现是没有意义的,所以我更愿意使用关联类型。
感谢您的宝贵时间:-)
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.
避免一生是不可能的。所有引用都有生命周期,编译器可以为您推断出其中一些生命周期,而您必须自己显式注释其中一些生命周期。注意:编译器并不总是正确的,因此有时尽管有编译器的推论,您还是必须显式注释生命周期。
In that case, I can have Struct
implement Trait<(&i64, &String)>
without the lifetime issue I had with an associated type.
是的,因为编译器为这些引用推断的生命周期恰好有效,但您不应该害怕在需要时自己显式注释它们。
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.
好吧,那么让我们使用关联类型。这是带有所有必要的生命周期注释的代码:
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
}
我有一些关联类型的特征,它的一些函数将这种类型的引用作为输入:
trait Trait {
type Value;
fn do_something(&self, value: &Self::Value);
}
在实现这个特性的一个结构中,Value
是一个元组,因为我需要将多个值传递给do_something
:
struct Struct {}
impl Trait for Struct {
type Value = (i64, String);
fn do_something(&self, (a, b): &(i64, String)) {
println!("{} {}", a, b);
}
}
然而,当我在实践中使用Struct
时,我碰壁了。要么我这样做:
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
}
但随后我失去了元组中任何非 Copy
类型的所有权。或者,我可以这样做:
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);
}
有效,但语法非常繁重。
有没有人知道如何以更简洁的方式完成我想要的?我试图让 Struct::Value
成为 (&i64, &String)
类型,但随后借用检查器抱怨这些引用需要生命周期,我希望尽可能避免这种情况。
我尝试的另一种选择是使用类型参数(因此,Trait<Value>
)而不是关联类型。在这种情况下,我可以让 Struct
实现 Trait<(&i64, &String)>
而不会出现关联类型的生命周期问题。它有效,但在我的项目中,Struct
有多个 Trait
的实现是没有意义的,所以我更愿意使用关联类型。
感谢您的宝贵时间:-)
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.
避免一生是不可能的。所有引用都有生命周期,编译器可以为您推断出其中一些生命周期,而您必须自己显式注释其中一些生命周期。注意:编译器并不总是正确的,因此有时尽管有编译器的推论,您还是必须显式注释生命周期。
In that case, I can have
Struct
implementTrait<(&i64, &String)>
without the lifetime issue I had with an associated type.
是的,因为编译器为这些引用推断的生命周期恰好有效,但您不应该害怕在需要时自己显式注释它们。
It works, but in my project it never makes sense for
Struct
to have more than one implementation ofTrait
, so I'd much prefer to use an associated type.
好吧,那么让我们使用关联类型。这是带有所有必要的生命周期注释的代码:
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
}