copy関数とストリームイテレータを使った一行出力コード
以前とある記事でコメントを頂いたときにこんなコードが書いてありました。
std::copy(xs.begin(), xs.end(), std::ostream_iterator<int>(std::cout, ","));
当時は全然意味がわからなかったのでとりあえずスルーしてたのですが、ストリームイテレータとSTL配列操作テンプレート関数の学習を経て、ようやく読めるようになりました。
まずはcopy関数から見てみましょう。
ある配列を別の配列にコピーするための関数です。
#include <iostream> #include <algorithm> using namespace std; int main () { int data1[] = {10,20,30}; int data2[3]; // data1の全ての要素をdata2へコピー copy(data1,data1+3,data2); for(int i=0;i<3;++i){ cout << data2[i] << endl; } return 0; }
$ main 10 20 30
もちろん他の関数と同じく、イテレータを渡すこともできます。
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main () { vector<int> data1; vector<int> data2; data1.push_back(10); data1.push_back(20); data1.push_back(30); // data2への挿入イテレータを用意 back_insert_iterator<vector<int>> iit_data2( data2 ); // data1の全ての要素をdata2へコピー copy(data1.begin(),data1.end(),iit_data2); vector<int>::iterator it = data2.begin(); vector<int>::iterator end = data2.end(); for(;it!=end;++it) { cout << *it << endl; } return 0; }
$ main 10 20 30
ばっちりコピーが動いていますね。
さて冒頭の処理に戻ります。
std::copy(xs.begin(), xs.end(), std::ostream_iterator<int>(std::cout, ","));
これはつまり、xsのデータをostream_iteratorで得たイテレータにコピーしているという処理になります。
そしてostream_iteratorというのは出力ストリームイテレータなので画面にxsの内容が出力されるということになります。
#include <iostream> #include <vector> #include <algorithm> using namespace std; int main () { vector<int> xs; xs.push_back(10); xs.push_back(20); xs.push_back(30); copy(xs.begin(),xs.end(),ostream_iterator<int>(cout,"\n")); return 0; }
$ main 10 20 30
コードがとてもスッキリしましたね。
ある配列やイテレータのデータの中身を出力したいだけの処理を書く場合、このやり方を使えば楽に書けそうですね。
ただこの書き方って一般的によく使われるような処理なのかどうかはちょっとわかりませんが。