今まで,std::istream から std::string 辺りに一括で読み込む関数を適当に書いていたのですが,これを少し真面目に実装してみます.最初は,std::getline(in, s, char_traits
#include <istream> #include <iterator> namespace clx { template <class Ch, class Tr, class Container> std::basic_istream<Ch, Tr>& read(std::basic_istream<Ch, Tr>& in, Container& dest) { typedef typename Container::value_type value_type; typedef typename Container::size_type size_type; typedef std::basic_istream<Ch, Tr> istream_type; typedef typename istream_type::ios_base ios_type; size_type extracted = 0; const size_type n = dest.max_size(); typename ios_type::iostate err = ios_type::goodbit; typename std::basic_istream<Ch, Tr>::sentry se(in, true); if (se) { try { dest.clear(); std::insert_iterator<Container> out(dest, dest.end()); typename istream_type::int_type c = in.rdbuf()->sgetc(); while (extracted < n && !Tr::eq_int_type(c, Tr::eof())) { value_type elem; if (in.rdbuf()->sgetn(reinterpret_cast<Ch*>(&elem), sizeof(value_type)) <= 0) { err |= ios_type::failbit; break; } *out = elem; ++out; ++extracted; c = in.rdbuf()->sgetc(); } if (Tr::eq_int_type(c, Tr::eof())) err |= ios_type::eofbit; else err |= ios_type::failbit; // larger than max_size } catch (...) { in.setstate(std::ios_base::badbit); } } if (!extracted) err |= ios_type::failbit; if (err) in.setstate(err); return in; } }
std::string でなくとも max_size(), clear(), insert() を持つコンテナであれば dest (第 2 引数)として指定する事ができます.例えば,std::vector
追記
後で思ったのですが,対象が std::string (と std::vector
std::istreambuf_iterator<char> input(in); std::istreambuf_iterator<char> last; std::insert_iterator<std::string> out(dest, dest.end()); std::copy(input, last, out);