我有一个非常简单的代码,无法编译:
struct X;
struct A {
field: Option<Box<X>>,
}
impl A {
pub fn get_field(&self) -> Option<&X> {
return self.field.map(|value| &*value);
}
}
Run Code Online (Sandbox Code Playgroud)
struct X;
struct A {
field: Option<Box<X>>,
}
impl A {
pub fn get_field(&self) -> Option<&X> {
return self.field.map(|value| &*value);
}
}
Run Code Online (Sandbox Code Playgroud)
我真的不明白为什么这行不通。
我真的不明白为什么这行不通。
您的代码定义了一个结构A,该结构可能会或可能不会X在堆中(不在堆栈中)保存一个。
在该方法中get_field,已给您对struct的引用,但X如果可能的话,您希望获得对inner的引用。
以上只是通过查看的功能签名和struct定义得出的结论A。
查看函数体,self.field类型为Option<_>,map是其方法。查看有关以下内容的文档Option::map:
Run Code Online (Sandbox Code Playgroud)pub fn map<U, F>(self, f: F) -> Option<U> where F: FnOnce(T) -> U,通过将函数应用于包含的值来映射
Option<T>到Option<U>。
它接受只能运行一次的闭包,Box<X>在您的情况下接受a ,然后根据您的函数返回类型应返回&X。它看起来像一个完美的搭配乍一看,因为如果value: Box<X>再*value: X和&*value: &X,但不编译!怎么了?
如果您仔细查看签名,map就会发现它有两个参数,而不是一个。第一个参数是“方法接收器” self,其类型为Self。
在Rust中,这意味着此调用将需要消耗方法接收器;调用后,用于调用该方法的对象将不再有效。
但是,您的get_field方法不允许删除方法接收方self.field:self只是对它的引用A,所以self.field也只是对的引用。然后,您将无法打电话map消费self.field。
解决方案是使用as_ref:
Run Code Online (Sandbox Code Playgroud)pub fn as_ref(&self) -> Option<&T>从转换
Option<T>为Option<&T>。
尽管它说从转换Option<T>,但是从签名中您可以看到它接受&Option<T>,因此它只是&向内移动。现在您可以使用了map。
pub fn get_field(&self) -> Option<&X> {
return self.field.as_ref().map(|value| &*value);
}
Run Code Online (Sandbox Code Playgroud)
现在可以了。
| 归档时间: |
|
| 查看次数: |
271 次 |
| 最近记录: |