#include <vector> #include <iostream> int main(){ std::vector<int> u, v; std::vector<std::vector<int>*> m; m.push_back(&u); m.push_back(&v); for(int i = 0; i < 5; i++){ u.push_back(i); v.push_back(-3 * i); } u[4] = 100; v[2] *= -1; for(std::vector<std::vector<int>*>::iterator mit = m.begin(); mit != m.end(); ++mit){ for(std::vector<int>::iterator it = (*mit)->begin(); it != (*mit)->end(); ++it){ std::cout << *it << std::endl; } } return 0; }
STL のコンテナには参照型を格納できないという噂なのでポインタを使った。
これに相当するものを D 言語 で。Tango 0.99.7 と DMD 1.033 を使用。tango.util.collection.ArraySeq 版から。
import tango.util.collection.ArraySeq; import tango.io.Stdout; int main(){ auto u = new ArraySeq!(int); auto v = new ArraySeq!(int); auto m = new ArraySeq!(ArraySeq!(int)); m.append(u); m.append(v); for(int i; i < 5; i++){ u.append(i); v.append(-3 * i); } u[4] = 100; // opIndexAssign は使える v[2] = -1 * v[2]; // opIndexMulAssign したいのにッ foreach(e; m){ foreach(f; e){ Stdout(f).newline; } } return 0; }
tango.util.collection.ArraySeq.ArraySeq
はクラスであり、D ではクラスは参照型である。
tango.util.container.more.Vector は実にアレ。
import tango.util.container.more.Vector; import tango.io.Stdout; int main(){ Vector!(int, 5) u, v; Vector!(Vector!(int, 5)*, 2) m; m.add(&u); m ~= &v; // alias add opCatAssign; されている for(int i; i < 5; i++){ u.add(i); v.add(-3 * i); } u[4] = 100; // opIndexAssign は使える v[2] = -1 * v[2]; // opIndexMulAssign したいのにッ foreach(e; m.slice){ foreach(f; (*e)[]){ // alias slice opSlice; されている Stdout(f).newline; } } return 0; }
tango.util.container.more.Vector.Vector
は構造体で、構造体は値型なので Vector
のポインタを Vector
に格納。固定長なのは個性としても、イテレータというか Vector#opApply
が LIFO 的で、つまり最近追加したものから古いものへと順に出てくる。よくあるものとは逆順。かといって Vector#opApplyReverse
が実装されているわけでもない。そのため、Vector#slice
で配列にして foreach
しなければならない。opApplyReverse
は ArraySeq
でも使えないけど。この辺の自由度は STL 最強か。
それはさておき、これら 3 つの出力結果はいずれも次のようになるはず。
0 1 2 3 100 0 -3 6 -9 -12
結論としては、D に opIndex*Assign
が欲しいのとイテレータ周辺を改良してほしいということ。