回答編集履歴
1
文言の追加とコードの微修正
test
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
parent を enum で実装していますが、trait を導入してジェネリクスにしてしまうのはどうでしょう。(PhantomData とかがでてきて面倒な形になってしまいましたが、もっといい実装があるかもしれません)
|
1
|
+
parent を enum で実装していますが、trait を導入してジェネリクスにしてしまうのはどうでしょう。(下記ではPhantomData とかがでてきて面倒な形になってしまいましたが、もっといい実装があるかもしれません)
|
2
2
|
|
3
|
+
わたしもぼんやりとしか理解できていませんが、元のコードが動かない理由には variance とかがかかわっているように思います。https://blog.ymgyt.io/entry/lifetime-and-variance/
|
3
|
-
|
4
|
+
`&'a mut T` は `T` に対して invariant なので、参照を含むものの `&mut` をとると、ライフタイムの関係が壊れてしまいそうです。
|
5
|
+
(`Parent(&'b mut Stack<'a, 'a, T>)`のところの`'a`)
|
4
|
-
ジェネリクスにすれば、そのあたりをコンパイラがいい感じにしてくれている
|
6
|
+
そこを別のライフタイムにしてどうにかしようとすると、別回答のコメントにあるように任意回のネストをうまく表現することができないです。ジェネリクスにすれば、そのあたりをコンパイラがいい感じにしてくれているように思います。
|
5
7
|
|
6
8
|
```rust
|
7
9
|
use std::collections::HashMap;
|
@@ -30,12 +32,6 @@
|
|
30
32
|
data: HashMap<u32, T>,
|
31
33
|
}
|
32
34
|
|
33
|
-
trait MemoryLike<T> {
|
34
|
-
fn alloc(&mut self, id: u32, value: T);
|
35
|
-
fn free(&mut self, id: u32);
|
36
|
-
fn len(&self) -> usize;
|
37
|
-
}
|
38
|
-
|
39
35
|
impl<T> Memory<T> {
|
40
36
|
fn new() -> Self {
|
41
37
|
Self {
|
@@ -44,7 +40,13 @@
|
|
44
40
|
}
|
45
41
|
}
|
46
42
|
|
43
|
+
trait Parent<T> {
|
44
|
+
fn alloc(&mut self, id: u32, value: T);
|
45
|
+
fn free(&mut self, id: u32);
|
46
|
+
fn len(&self) -> usize;
|
47
|
+
}
|
48
|
+
|
47
|
-
impl<T>
|
49
|
+
impl<T> Parent<T> for Memory<T> {
|
48
50
|
fn alloc(&mut self, id: u32, value: T) {
|
49
51
|
if self.data.insert(id, value).is_some() {
|
50
52
|
panic!()
|
@@ -62,7 +64,7 @@
|
|
62
64
|
}
|
63
65
|
}
|
64
66
|
|
65
|
-
struct Stack<'a, T, U:
|
67
|
+
struct Stack<'a, T, U: Parent<T>> {
|
66
68
|
ids: Vec<u32>,
|
67
69
|
parent: &'a mut U,
|
68
70
|
_p: PhantomData<T>,
|
@@ -78,8 +80,8 @@
|
|
78
80
|
}
|
79
81
|
}
|
80
82
|
|
81
|
-
impl<'a, T, U:
|
83
|
+
impl<'a, T, U: Parent<T>> Stack<'a, T, U> {
|
82
|
-
fn nest<'b>(&'b mut self) -> Stack<'b, T, S
|
84
|
+
fn nest<'b>(&'b mut self) -> Stack<'b, T, Self> {
|
83
85
|
Stack {
|
84
86
|
ids: vec![],
|
85
87
|
parent: self,
|
@@ -93,7 +95,7 @@
|
|
93
95
|
}
|
94
96
|
}
|
95
97
|
|
96
|
-
impl<T, U:
|
98
|
+
impl<T, U: Parent<T>> Parent<T> for Stack<'_, T, U> {
|
97
99
|
fn alloc(&mut self, id: u32, value: T) {
|
98
100
|
self.parent.alloc(id, value);
|
99
101
|
}
|
@@ -107,12 +109,11 @@
|
|
107
109
|
}
|
108
110
|
}
|
109
111
|
|
110
|
-
impl<T, U:
|
112
|
+
impl<T, U: Parent<T>> Drop for Stack<'_, T, U> {
|
111
113
|
fn drop(&mut self) {
|
112
114
|
for id in &self.ids {
|
113
115
|
self.parent.free(*id);
|
114
116
|
}
|
115
117
|
}
|
116
118
|
}
|
117
|
-
|
118
119
|
```
|