質問するログイン新規登録

質問編集履歴

3

追記2

2025/09/12 04:10

投稿

fana
fana

スコア12285

title CHANGED
File without changes
body CHANGED
@@ -206,4 +206,35 @@
206
206
 
207
207
  /* ... */
208
208
  }
209
- ```
209
+ ```
210
+
211
+ ---
212
+
213
+ ## 追記2
214
+
215
+ 「いやいやそうじゃねぇよ,ごちゃごちゃ言ってないでまず最初にスタックから取り出せと」という方向のご指摘,もっともだと思います.
216
+
217
+ ```C++
218
+ //何らかのタイミングでの処理
219
+ void XXX()
220
+ {
221
+ /* ... */
222
+
223
+ if( !TheStack.empty() )
224
+ {
225
+ //とにかく最初にやるべきことはこれだろ,と.
226
+ auto TakenOut = std::move( TheStack.top() ); //変な考えは捨てて取り出すべし
227
+ TheStack.pop(); //(ここでpopもやるかどうかというのは以降の実装の都合次第かもだが)
228
+
229
+ //とにかく取り出したなら,そもそもここで変な問題は起きない
230
+ TakenOut->DoSomething();
231
+
232
+ //---
233
+
234
+ //(必要なら TakenOut をスタックに再度積み直すだとかいう話はあるかもだが,それは今の「問題」とは別の話)
235
+ if( 何らかの判断 ){ TheStack.push( std::move(TakenOut) ); }
236
+ }
237
+
238
+ /* ... */
239
+ }
240
+ ```

2

そもそもどうなのか?という指摘を受けての考えを追記

2025/09/11 02:19

投稿

fana
fana

スコア12285

title CHANGED
File without changes
body CHANGED
@@ -105,3 +105,105 @@
105
105
  Owner.push( std::move( ToBePushed ) );
106
106
  }
107
107
  ```
108
+
109
+ ---
110
+
111
+ ## 追記
112
+
113
+ 「そもそも要素側からスタックを操作すること自体がどうなのか?」というご指摘,もっともだと思います.
114
+ その方面(要素側からスタックを操作しないようにする)で考えると,こんな↓形になりました.
115
+ こちらに関しても「いや,そうじゃねぇよ」とか「やるにしてもこうだろう」等々ご教示願えればありがたいです.
116
+
117
+ ```C++
118
+ //要素が直接スタックを操作するのではなくて,
119
+ //要素からは「スタックをこのように操作したい」という要求を戻り値で返す.
120
+ //(→で,戻り値を受け取った側でスタックを操作する)
121
+
122
+ struct IStackElem;
123
+
124
+ //スタック
125
+ using Stack_t = std::stack< std::unique_ptr<IStackElem> >;
126
+
127
+ //スタックに対するPush操作
128
+ class Push
129
+ {
130
+ public:
131
+ //ctorでPushすべきものを指定
132
+ Push( std::unique_ptr<IStackElem> ToBePushed ) : m_ToBePushed( std::move(ToBePushed) ) {}
133
+ //操作実施
134
+ void Exec( Stack_t &Stk ){ if(m_ToBePushed)Stk.push( std::move(m_ToBePushed) ); }
135
+ private:
136
+ std::unique_ptr<IStackElem> m_ToBePushed;
137
+ };
138
+
139
+ //スタックに対するPop操作
140
+ class Pop
141
+ {
142
+ public:
143
+ //ctorでPopすべき回数を指定
144
+ Pop( size_t nPop=1 ) : m_nPop(nPop) {}
145
+ //操作実施
146
+ void Exec( Stack_t &Stk )
147
+ {
148
+ const size_t n = std::min( m_nPop, Stk.size() );
149
+ for( size_t i=0; i<n; ++i )Stk.pop();
150
+ }
151
+ private:
152
+ size_t m_nPop;
153
+ };
154
+
155
+ //スタックに対する操作要求
156
+ using StackOp = std::variant< Push, Pop >;
157
+
158
+ //スタックに積まれるやつ
159
+ struct IStackElem
160
+ {
161
+ virtual ~IStackElem() = default;
162
+
163
+ //※この型は専らスタックに積まれる使い方をされるという前提であって,
164
+ //このメソッドが呼ばれるときとは,自身がスタックのtopである場合である.
165
+ //
166
+ //戻り値として,所属スタックに対して実施されるべき操作シーケンスを返す.
167
+ virtual std::vector<StackOp> DoSomething() = 0;
168
+ };
169
+
170
+ //----------
171
+ //件の要素例の実装
172
+ struct Problem : public IStackElem
173
+ {
174
+ public:
175
+ Problem( size_t nPop, std::unique_ptr<IStackElem> ToBePushed )
176
+ : m_nPop(nPop), m_ToBePushed(std::move(ToBePushed))
177
+ {}
178
+
179
+ virtual std::vector<StackOp> DoSomething() override
180
+ {//m_nPop個だけ pop し,その後で m_ToBePushed を push したい
181
+ std::vector<StackOp> OPSeq;
182
+ OPSeq.emplace_back( Pop(m_nPop) );
183
+ OPSeq.emplace_back( Push( std::move(m_ToBePushed) ) );
184
+ return OPSeq;
185
+ };
186
+
187
+ private:
188
+ size_t m_nPop;
189
+ std::unique_ptr<IStackElem> m_ToBePushed;
190
+ };
191
+
192
+ //----------
193
+ //何らかのタイミングでの処理
194
+ void XXX()
195
+ {
196
+ /* ... */
197
+
198
+ if( !TheStack.empty() )
199
+ {
200
+ auto OPs = TheStack.top()->DoSomething();
201
+ for( auto &OP : OPs ) //返されてきた操作要求を実施する
202
+ {
203
+ std::visit( [&TheStack]( auto &OP ){ OP.Exec(TheStack); }, OP );
204
+ }
205
+ }
206
+
207
+ /* ... */
208
+ }
209
+ ```

1

タグを増やした

2025/09/09 07:18

投稿

fana
fana

スコア12285