Option
から参照を引き出して、呼び出し元の特定の存続期間とともに返すにはどうすればよいですか?
具体的には、Box<Foo>
が含まれているBar
からOption<Box<Foo>>
への参照を借用したいと思います。私は私ができるだろうと思った:
impl Bar {
fn borrow(&mut self) -> Result<&Box<Foo>, BarErr> {
match self.data {
Some(e) => Ok(&e),
None => Err(BarErr::Nope),
}
}
}
...しかし、その結果:
error: `e` does not live long enough
--> src/main.rs:17:28
|
17 | Some(e) => Ok(&e),
| ^ does not live long enough
18 | None => Err(BarErr::Nope),
19 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the body at 15:54...
--> src/main.rs:15:55
|
15 | fn borrow(&mut self) -> Result<&Box<Foo>, BarErr> {
| _______________________________________________________^ starting here...
16 | | match self.data {
17 | | Some(e) => Ok(&e),
18 | | None => Err(BarErr::Nope),
19 | | }
20 | | }
| |_____^ ...ending here
error[E0507]: cannot move out of borrowed content
--> src/main.rs:16:15
|
16 | match self.data {
| ^^^^ cannot move out of borrowed content
17 | Some(e) => Ok(&e),
| - hint: to prevent move, use `ref e` or `ref mut e`
うーん、わかりました。そうでないかもしれない。私がやりたいことは Option::as_ref
に関連しているように、漠然と見えます。
impl Bar {
fn borrow(&mut self) -> Result<&Box<Foo>, BarErr> {
match self.data {
Some(e) => Ok(self.data.as_ref()),
None => Err(BarErr::Nope),
}
}
}
...しかし、それも機能しません。
私が問題を抱えている完全なコード:
#[derive(Debug)]
struct Foo;
#[derive(Debug)]
struct Bar {
data: Option<Box<Foo>>,
}
#[derive(Debug)]
enum BarErr {
Nope,
}
impl Bar {
fn borrow(&mut self) -> Result<&Box<Foo>, BarErr> {
match self.data {
Some(e) => Ok(&e),
None => Err(BarErr::Nope),
}
}
}
#[test]
fn test_create_indirect() {
let mut x = Bar { data: Some(Box::new(Foo)) };
let mut x2 = Bar { data: None };
{
let y = x.borrow();
println!("{:?}", y);
}
{
let z = x2.borrow();
println!("{:?}", z);
}
}
私がやろうとしていることはここで有効であると合理的に確信しています。
まず第一に、あなたは&mut self
を必要としません。
照合するときは、参照としてe
を照合する必要があります。 e
の参照を返そうとしていますが、その存続期間はそのmatchステートメントのみです。
enum BarErr {
Nope
}
struct Foo;
struct Bar {
data: Option<Box<Foo>>
}
impl Bar {
fn borrow(&self) -> Result<&Foo, BarErr> {
match self.data {
Some(ref x) => Ok(x),
None => Err(BarErr::Nope)
}
}
}
あなたは確かに使用することができます Option::as_ref
、先に使用する必要があります:
impl Bar {
fn borrow(&self) -> Result<&Box<Foo>, BarErr> {
self.data.as_ref().ok_or(BarErr::Nope)
}
}
可変参照のコンパニオンメソッドがあります: Option::as_mut
:
impl Bar {
fn borrow_mut(&mut self) -> Result<&mut Box<Foo>, BarErr> {
self.data.as_mut().ok_or(BarErr::Nope)
}
}
おそらくmap
を追加して、Box
ラッパーを削除します。
impl Bar {
fn borrow(&self) -> Result<&Foo, BarErr> {
self.data.as_ref().ok_or(BarErr::Nope).map(|x| &**x)
}
fn borrow_mut(&mut self) -> Result<&mut Foo, BarErr> {
self.data.as_mut().ok_or(BarErr::Nope).map(|x| &mut **x)
}
}
参照:
Rust 1.26、match ergonomicsの時点で、次のように記述できます。
fn borrow(&mut self) -> Result<&Box<Foo>, BarErr> {
match &self.data {
Some(e) => Ok(e),
None => Err(BarErr::Nope),
}
}