我正在阅读Rust书的生命周章,我在这个例子中看到了命名/显式生命周期:
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let x; // -+ x goes into scope
// |
{ // |
let y = &5; // ---+ y goes into scope
let f = Foo { x: y }; // ---+ f goes into scope
x = &f.x; // | | error here
} // ---+ f and y go out of scope
// |
println!("{}", x); // |
} // -+ x goes out …Run Code Online (Sandbox Code Playgroud) 在这个问题中,出现了一个问题,可以通过改变将泛型类型参数用于关联类型的尝试来解决.这引发了一个问题"为什么相关类型在这里更合适?",这让我想知道更多.
此RFC通过以下方式阐明特征匹配:
- 将所有特征类型参数视为输入类型,和
- 提供相关类型,即输出类型.
RFC使用图形结构作为激励示例,这也在文档中使用,但我承认不完全理解相关类型版本相对于类型参数化版本的好处.主要的是该distance方法不需要关心Edge类型.这很好,但似乎有一点点关联类型的原因.
我发现在实践中使用相关类型非常直观,但在决定在我自己的API中何时何地使用它们时,我发现自己很挣扎.
在编写代码时,何时应该在泛型类型参数上选择关联类型,何时应该相反?
请考虑以下代码:
trait Trait<T> {}
fn foo<'a>(_b: Box<dyn Trait<&'a usize>>) {}
fn bar(_b: Box<dyn for<'a> Trait<&'a usize>>) {}
Run Code Online (Sandbox Code Playgroud)
这两个函数foo和bar似乎接受Box<Trait<&'a usize>>,虽然foo比更简明做它bar.他们之间有什么区别?
另外,在什么情况下我需要for<>像上面那样的语法?我知道Rust标准库在内部使用它(通常与闭包有关),但为什么我的代码需要它呢?
我在迭代器上应用了一个闭包,我想使用stable,所以我想返回一个盒装Iterator.这样做的显而易见的方法如下:
struct Foo;
fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo>> {
Box::new(myvec.iter())
}
Run Code Online (Sandbox Code Playgroud)
这是失败的,因为借用检查器无法推断出适当的生命周期.
经过一番研究,我找到了正确的方法来返回迭代器?,这让我想补充一下+ 'a:
fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &'a Foo> + 'a> {
Box::new(myvec.iter())
}
Run Code Online (Sandbox Code Playgroud)
但我不明白
我有一个特征Matrix和通用功能semi_def<T: Matrix>(x: &T),我想对该特征进行操作。该功能需要一个操作员特征,例如Mul,在上实现T。但是,如果引用之一是对局部变量的引用,我似乎无法使一生愉快。当其中之一只是本地临时引用时,如何在类型约束中编写引用的生存期?
use std::ops::Mul;
trait Matrix: Clone {
fn transpose(self) -> Self;
}
#[derive(Clone)]
struct DenseMatrix {
n_rows: usize,
n_columns: usize,
elements: Vec<f64>,
}
impl Matrix for DenseMatrix {
fn transpose(self) -> Self {
unimplemented!()
}
}
impl<'a, 'b> Mul<&'b DenseMatrix> for &'a DenseMatrix {
type Output = DenseMatrix;
fn mul(self, _rhs: &'b DenseMatrix) -> Self::Output {
unimplemented!()
}
}
fn semi_def<'a, T: Matrix>(x: &'a T) -> T
where
&'a T: …Run Code Online (Sandbox Code Playgroud)