正しい 演算子"<<" の定義の仕方
C++で何らかの型を定義して、その型を文字列に変換したいとき、演算子"<<" をストリームに対し定義してやると便利だ。
class Hoge{ public: //たとえば配列のような型だったとする size_t size()const{/*略*/} int operator[](size_t i)const{/*略*/} /*略*/ }; Hoge hoge; std::cout << hoge << std::endl;
よくありがちな失敗は
std::ostream& operator<<(std::ostream& os, const Hoge& rhs){ //クラスをstringstreamに対し文字列化する for(size_t i = 0;i<rhs.size();i++){ os << hoge[i] } return os; }
のような形だろう。これだと、
- wchar_tに対応しない
- 途中で失敗したばあいに出力にごみが残る
- フラグ・ロケール・精度を考慮しない
でこの定義の正しいやり方は以下のようになる
template<typename _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& os, const Hoge& rhs){ std::basic_ostringstream<_CharT, _Traits> s;//いったんstringstreamを宣言 //フラグ・ロケール・精度をコピー s.flags(os.flags()); s.imbue(os.getloc()); s.precision(os.precision()); //クラスをstringstreamに対し文字列化する for(size_t i = 0;i<rhs.size();i++){ s << hoge[i] } //文字列化し出力 return os << s.str(); }
- テンプレートで定義する
- 出力先からstringstreamに各種情報をコピーする
- 一度stringstreamに出力する
- 出力先へstringstreamから文字列化し出力