回答編集履歴

1

文言の追加とコードの微修正

2025/01/24 07:41

投稿

bsdfan
bsdfan

スコア4899

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
- わたしもぼんやりとしか理解できていませんが、元のコードが動かない理由には variance とかがかかわっているように思います。`&'a mut T` は `T` に対して invariant なので、参照を含むものの `&mut` をとると、ライフタイムの関係が壊れてしまいそうです。
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> MemoryLike<T> for Memory<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: MemoryLike<T>> {
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: MemoryLike<T>> Stack<'a, T, U> {
83
+ impl<'a, T, U: Parent<T>> Stack<'a, T, U> {
82
- fn nest<'b>(&'b mut self) -> Stack<'b, T, Stack<'a, T, U>> {
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: MemoryLike<T>> MemoryLike<T> for Stack<'_, 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: MemoryLike<T>> Drop for Stack<'_, 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
  ```