以前の記事の
C++でファイル読込み パターン別まとめ - Gobble up pudding
で最後に書いた例のstreambuf_iteratorの仕組みですが、
おおまかにどうなっているのかわかりました!
C++標準ライブラリのiteratorを継承して、
内部でファイルポインタを扱っているようです。
iteratorについてはこのあたりが参考になりそうです。
iterator - C++ Reference
https://sites.google.com/site/cpprefjp/reference/iterator/iterator
イテレータを実装しよう
libstdc++: std::iterator< _Category, _Tp, _Distance, _Pointer, _Reference > Struct Template Reference
streambuf_iteratorは
http://www.cplusplus.com/reference/iterator/istreambuf_iterator/
の実装例を参考に書いてみました。
ただし、Proxyは使っていません。この実装例を見て不思議なのが
内部クラスでProxyはこのように定義されているのに
class proxy { charT keep_; streambuf_type* sbuf_; public: proxy (charT c, streambuf_type* sbuf) : keep_(c), sbuf_(sbuf) { } charT operator*() {return keep_;} };
istreambuf_iterator(const proxy& p) throw(): sbuf_(p.sbuf_) { }
と書かれている部分ですね。
なんでprivateメンバーにアクセスできるんだろ。
なぜかコンパイラがエラー吐かないし。
g++でもVC++でもエラー吐きませんでした。
それどころかp.sbuf_の部分をp.sbとかにしてもエラーにならない。
なぜだ……(*´Д`)。。。まぁいいか*1。
ソースコード gist
iotest.cpp streambuf_iterator simple implementatio ...
補足ですが、stringのコンストラクタで使っているのは
string( input_iterator[コピー元の最初のイテレータ], input_iterator[コピー元の最後のイテレータ] );
ってタイプのやつです。
テストに使うファイル
test.txt
すとりーむばふいてれーたーの かんいじっそうてすとだお(*´ω`)
プロジェクトのディレクトリ(VC++)かプログラムと同じ場所(g++)においてください。
コンパイル
VC++
C++ > プリプロセッサ > プリプロセッサの定義に USE_MY_LIB_ を追加(偽物使う場合) リンカー > システム > サブシステム > コンソール (/SUBSYSTEM:CONSOLE) になっている状態でビルドでたぶんOK
g++
g++ -DUSE_MY_LIB_ -o iotest.exe iotest.cpp
実行結果
USE DUMMY LIB! [すとりーむばふいてれーたーの かんいじっそうてすとだお(*´ω`) ]
マジな実装は下記のようです。
streambuf_iterator.h source code [include/c++/7.2.1/bits/streambuf_iterator.h] - Woboq Code Browser
*1:呼び出されていない部分はコンパイルされません