質問編集履歴

1

その後を追加

2016/03/01 15:12

投稿

Chironian
Chironian

スコア23272

test CHANGED
File without changes
test CHANGED
@@ -29,3 +29,363 @@
29
29
  なぜに範囲ベースforはiteratorを返さないのでしょう?
30
30
 
31
31
  [for-range-declaration = *__begin;](http://cpplover.blogspot.jp/2009/08/n2930-range-based-for-loop.html)じゃなくて、`for-range-declaration = __begin;`なら良かったのに。
32
+
33
+
34
+
35
+ ---
36
+
37
+ 【その後】
38
+
39
+ その後、調べていて、ランダム・アクセス・イレテータでないコンテナの場合、std:distance()はリストを追跡するらしいことが分かりました。ということは同様にoperator[]も追跡する筈ですね。(何を今更なのですが。)
40
+
41
+ 今はvectorで範囲ベースforを使ってますが一部はforward_listへ変更します。これを見越すと、インデックスを使うためにはイテレータ型のfor文へ変更しインデックスも追加する必要があります。for文がごちゃごちゃになり、範囲ベースforとの落差に悶え死にそうでした。しかも、autoの型が変わってしまうし...
42
+
43
+
44
+
45
+ 個人的にこれらが許せないので、yumetodoさんのリンク先の記事からヒントを得て、ツールを作りました。
46
+
47
+ 考え方は、自作の隠しイテレータをコンパイラへ返して、それがインクリメントされた時にインデックスも一緒にインクリメントするイメージです。
48
+
49
+ ですので、listでも使えますし、listのイテレータをdistanceした時のような追跡処理も発生しません。そして、autoで推論される型は同じコンテナの要素のままですので、範囲ベースforブロック内の変更も不要です。
50
+
51
+
52
+
53
+ ```C++
54
+
55
+ #include <iterator>
56
+
57
+
58
+
59
+ // ***************************************************************************
60
+
61
+ // 範囲ベースforにインデックス機能を追加する
62
+
63
+ // ***************************************************************************
64
+
65
+
66
+
67
+ namespace staff_only
68
+
69
+ {
70
+
71
+
72
+
73
+ //----------------------------------------------------------------------------
74
+
75
+ // 隠しイテレータ・クラス
76
+
77
+ //----------------------------------------------------------------------------
78
+
79
+
80
+
81
+ template<typename tValueType, typename tParentIterator>
82
+
83
+ class Iterator
84
+
85
+ {
86
+
87
+ tParentIterator mParentIterator;
88
+
89
+ std::size_t& mIndexReference;
90
+
91
+ public:
92
+
93
+ explicit Iterator(tParentIterator iIterator, std::size_t& iIndexReference) :
94
+
95
+ mParentIterator(iIterator),
96
+
97
+ mIndexReference(iIndexReference)
98
+
99
+ { }
100
+
101
+
102
+
103
+ tValueType& operator*() {return *mParentIterator;}
104
+
105
+ tParentIterator& operator++()
106
+
107
+ {
108
+
109
+ ++mParentIterator;
110
+
111
+ ++mIndexReference;
112
+
113
+ return mParentIterator;
114
+
115
+ }
116
+
117
+ bool operator==(Iterator const& rhs) {return mParentIterator==rhs.mParentIterator;}
118
+
119
+ bool operator!=(Iterator const& rhs) {return mParentIterator!=rhs.mParentIterator;}
120
+
121
+ };
122
+
123
+
124
+
125
+ //----------------------------------------------------------------------------
126
+
127
+ // コンテナ
128
+
129
+ //----------------------------------------------------------------------------
130
+
131
+
132
+
133
+ template<class tContainer>
134
+
135
+ class Indexer
136
+
137
+ {
138
+
139
+ typedef typename tContainer::value_type ValueType;
140
+
141
+ typedef typename tContainer::iterator ParentIterator;
142
+
143
+ typedef Iterator<ValueType, ParentIterator> InnerIterator;
144
+
145
+
146
+
147
+ // Indexer実体
148
+
149
+ tContainer& mContainer;
150
+
151
+ std::size_t& mIndexReference;
152
+
153
+ public:
154
+
155
+ explicit Indexer(tContainer& iContainer, std::size_t& iIndexReference) :
156
+
157
+ mContainer(iContainer),
158
+
159
+ mIndexReference(iIndexReference)
160
+
161
+ {
162
+
163
+ mIndexReference=0;
164
+
165
+ }
166
+
167
+ InnerIterator begin()
168
+
169
+ {
170
+
171
+ return InnerIterator(mContainer.begin(), mIndexReference);
172
+
173
+ }
174
+
175
+ InnerIterator const end() const
176
+
177
+ {
178
+
179
+ return InnerIterator(mContainer.end(), mIndexReference);
180
+
181
+ }
182
+
183
+ };
184
+
185
+
186
+
187
+ //----------------------------------------------------------------------------
188
+
189
+ // 生配列
190
+
191
+ //----------------------------------------------------------------------------
192
+
193
+
194
+
195
+ template<class tValueType, size_t tDim>
196
+
197
+ class Indexer<tValueType[tDim]>
198
+
199
+ {
200
+
201
+ typedef tValueType* ParentIterator;
202
+
203
+ typedef Iterator<tValueType, ParentIterator> InnerIterator;
204
+
205
+
206
+
207
+ // Indexer実体
208
+
209
+ typedef tValueType Container[tDim];
210
+
211
+ Container& mContainer;
212
+
213
+ std::size_t& mIndexReference;
214
+
215
+ public:
216
+
217
+ explicit Indexer(Container& iContainer, std::size_t& iIndexReference) :
218
+
219
+ mContainer(iContainer),
220
+
221
+ mIndexReference(iIndexReference)
222
+
223
+ {
224
+
225
+ mIndexReference=0;
226
+
227
+ }
228
+
229
+ InnerIterator begin()
230
+
231
+ {
232
+
233
+ return InnerIterator(&mContainer[0], mIndexReference);
234
+
235
+ }
236
+
237
+ InnerIterator const end() const
238
+
239
+ {
240
+
241
+ return InnerIterator(&mContainer[tDim], mIndexReference);
242
+
243
+ }
244
+
245
+ };
246
+
247
+ } // namespace staff_only
248
+
249
+
250
+
251
+ //----------------------------------------------------------------------------
252
+
253
+ // API
254
+
255
+ //----------------------------------------------------------------------------
256
+
257
+
258
+
259
+ template<class tContainer>
260
+
261
+ staff_only::Indexer<tContainer> getIndexer(tContainer& iContainer, std::size_t& iIndexReference)
262
+
263
+ {
264
+
265
+ return staff_only::Indexer<tContainer>(iContainer, iIndexReference);
266
+
267
+ }
268
+
269
+
270
+
271
+ // ***************************************************************************
272
+
273
+ // 使い方
274
+
275
+ // ***************************************************************************
276
+
277
+
278
+
279
+ #include <array>
280
+
281
+ #include <vector>
282
+
283
+ #include <forward_list>
284
+
285
+ #include <list>
286
+
287
+
288
+
289
+ #include <iostream>
290
+
291
+
292
+
293
+ int main()
294
+
295
+ {
296
+
297
+ struct TestClass
298
+
299
+ {
300
+
301
+ int x, y;
302
+
303
+ };
304
+
305
+ TestClass wRawArray[] = {{5,1}, {4,2}, {3,3}, {2,4}, {1,5}, {0,6}};
306
+
307
+ std::array<TestClass, 5> wArray ={{{4,2}, {3,3}, {2,4}, {1,5}, {0,6}}};
308
+
309
+ std::vector<TestClass> wVector = {{3,3}, {2,4}, {1,5}, {0,6}};
310
+
311
+ std::forward_list<TestClass> wForwardList= {{2,4}, {1,5}, {0,6}};
312
+
313
+ std::list<TestClass> wList = {{1,5}, {0,6}};
314
+
315
+
316
+
317
+ std::size_t wIndex;
318
+
319
+
320
+
321
+ std::cout << "raw-array\n";
322
+
323
+ for (auto& wData : getIndexer(wRawArray, wIndex)) {
324
+
325
+ std::cout << "[" << wIndex << "]=" << wData.x << ", " << wData.y << "\n";
326
+
327
+ }
328
+
329
+
330
+
331
+ std::cout << "\nstd::array\n";
332
+
333
+ for (auto& wData : getIndexer(wArray, wIndex)) {
334
+
335
+ std::cout << "[" << wIndex << "]=" << wData.x << ", " << wData.y << "\n";
336
+
337
+ }
338
+
339
+
340
+
341
+ std::cout << "\nstd::vector\n";
342
+
343
+ for (auto& wData : getIndexer(wVector, wIndex)) {
344
+
345
+ std::cout << "[" << wIndex << "]=" << wData.x << ", " << wData.y << "\n";
346
+
347
+ }
348
+
349
+
350
+
351
+ std::cout << "\nstd::forward_list\n";
352
+
353
+ for (auto& wData : getIndexer(wForwardList, wIndex)) {
354
+
355
+ std::cout << "[" << wIndex << "]=" << wData.x << ", " << wData.y << "\n";
356
+
357
+ }
358
+
359
+
360
+
361
+ std::cout << "\nstd::list\n";
362
+
363
+ for (auto& wData : getIndexer(wList, wIndex)) {
364
+
365
+ std::cout << "[" << wIndex << "]=" << wData.x << ", " << wData.y << "\n";
366
+
367
+ }
368
+
369
+
370
+
371
+ return 0;
372
+
373
+ }
374
+
375
+
376
+
377
+
378
+
379
+ ```
380
+
381
+
382
+
383
+ msvc2015とMinGW 5.2.0で動作確認してます。
384
+
385
+
386
+
387
+ 2点不満が残りました。orz
388
+
389
+ イテレータはこっそりインクリメントされているので、インデックスもこっそりインクリメントされます。範囲ベースforの仕様とも言えるのでこの点は許容することにしました。
390
+
391
+ インデックスのスコープがforの外側になってしまいます。内側にしたいのですが、範囲ベースforの構文に割り込めず諦め。