読者です 読者をやめる 読者になる 読者になる

Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

string型にファイルを一気読みできるstreambuf_iteratorのおおまかな仕組み

スポンサードリンク

f:id:fa11enprince:20150731121118j:plain
以前の記事の
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!
[すとりーむばふいてれーたーの
かんいじっそうてすとだお(*´ω`)
]

マジな実装は下記のようです。
GNU C++ STL: streambuf_iterator.h Source File

*1:呼び出されていない部分はコンパイルされません