「C++/ライブラリ/multi_stream」の編集履歴(バックアップ)一覧はこちら

C++/ライブラリ/multi_stream - (2008/12/12 (金) 22:46:41) の最新版との変更点

追加された行は緑色になります。

削除された行は赤色になります。

***概要 複数のostreamへ出力するストリームラッパクラス。~ コンストラクタの引数の展開にBoostを使ってるので要Boost。~ 手書きすればBoostなしでも可。 ***使い方 #codehighlight(C++){{ void func() { std::ofstream of; of.open("somefile") util::multi_ostream(std::cout, of); mt << "foobar" << std::endl; // 標準出力とファイルに"foobar"が出力される } }} ***コード #codehighlight(C++){{ /** @file multi_stream.h * @breif 複数のostreamへ出力するストリームクラス */ #ifndef UTIL_MULTI_STREAM_H #define UTIL_MULTI_STREAM_H #include <iostream> #include <vector> #include <boost/preprocessor.hpp> namespace util { namespace detail { //! コンストラクタで受け付けるostreamの最大数 #define ARGUMENT_MAX_COUNT 5 #define OSTREAM_ARRAY_ASSIGNMENT(z, n, data) outs_[n]=BOOST_PP_CAT(&os, n); #define BOOST_PP_LOCAL_MACRO(n) \ basic_multi_streambuf(BOOST_PP_ENUM_PARAMS(n, std::basic_ostream<Ch BOOST_PP_COMMA() Tr>& os)) \ : outs_(n), buf_(16) \ { \ setp(&(buf_[0]), (&(buf_[0])+buf_.size())); \ BOOST_PP_REPEAT(n, OSTREAM_ARRAY_ASSIGNMENT, ~) \ } #define BOOST_PP_LOCAL_LIMITS (1, BOOST_PP_EXPAND(ARGUMENT_MAX_COUNT)) /* 複数のostreamへ出力するためのstreambufクラス */ template <class Ch, class Tr=std::char_traits<Ch> > class basic_multi_streambuf : public std::basic_streambuf<Ch,Tr> { public: #include BOOST_PP_LOCAL_ITERATE() void add(std::basic_ostream<Ch, Tr>& os) { outs_.push_back(&os); } protected: int_type overflow(int_type c=Tr::eof()) { if(c!=Tr::eof()) { const size_t pos = pptr()-pbase(); if(buf_.size() >= pos+1) { buf_.resize(2*buf_.size()); setp(&(buf_[0]), (&(buf_[0])+buf_.size())); pbump(pos); } *pptr() = Tr::to_char_type(c); pbump(1); return Tr::not_eof(c); } return Tr::eof(); } int sync() { const size_t pos = pptr()-pbase(); for(ostreams::iterator it=outs_.begin(); it!=outs_.end(); ++it) { (*it)->write(&(buf_[0]), pos); (*it)->flush(); } pbump(pbase()-pptr()); return 0; } private: explicit basic_multi_streambuf<Ch, Tr>(const basic_multi_streambuf<Ch, Tr>&); basic_multi_streambuf<Ch, Tr> &operator=(const basic_multi_streambuf<Ch, Tr>&); typedef std::vector<std::basic_ostream<Ch,Tr>* > ostreams; ostreams outs_; std::vector<Ch> buf_; }; #define BOOST_PP_LOCAL_MACRO(n) \ basic_multi_ostream(BOOST_PP_ENUM_PARAMS(n, std::basic_ostream<Ch BOOST_PP_COMMA() Tr>& os)) \ : std::basic_iostream<Ch,Tr>(&streambuf_), streambuf_(BOOST_PP_ENUM_PARAMS(n, os)) \ {} #define BOOST_PP_LOCAL_LIMITS (1, BOOST_PP_EXPAND(ARGUMENT_MAX_COUNT)) /* 複数のostreamへ出力するためのラッパークラス */ template <class Ch, class Tr=std::char_traits<Ch> > class basic_multi_ostream : public std::basic_iostream<Ch,Tr> { public: #include BOOST_PP_LOCAL_ITERATE() ~basic_multi_ostream() {} private: explicit basic_multi_ostream(const basic_multi_ostream&); basic_multi_ostream &operator=(const basic_multi_ostream&); basic_multi_streambuf<Ch, Tr> streambuf_; }; } typedef detail::basic_multi_ostream<char> multi_ostream; typedef detail::basic_multi_ostream<wchar_t> multi_wostream; #undef ARGUMENT_MAX_COUNT #undef OSTREAM_ARRAY_ASSIGNMENT } #endif }}
***概要 複数のostreamへ出力するストリームラッパクラス。~ コンストラクタの引数の展開にBoostを使ってるので要Boost。~ 手書きすればBoostなしでも可。 ***使い方 #codehighlight(C++){{ void func() { std::ofstream of; of.open("somefile") util::multi_ostream(std::cout, of); mt << "foobar" << std::endl; // 標準出力とファイルに"foobar"が出力される } }} ***コード #codehighlight(C++){{ /** @file multi_stream.h * @breif 複数のostreamへ出力するストリームクラス */ #ifndef UTIL_MULTI_STREAM_H #define UTIL_MULTI_STREAM_H #include <iostream> #include <vector> #include <boost/preprocessor.hpp> namespace util { namespace detail { //! コンストラクタで受け付けるostreamの最大数 #define ARGUMENT_MAX_COUNT 5 #define OSTREAM_ARRAY_ASSIGNMENT(z, n, data) outs_[n]=BOOST_PP_CAT(&os, n); #define BOOST_PP_LOCAL_MACRO(n) \ basic_multi_streambuf(BOOST_PP_ENUM_PARAMS(n, std::basic_ostream<Ch BOOST_PP_COMMA() Tr>& os)) \ : outs_(n), buf_(16) \ { \ setp(&(buf_[0]), (&(buf_[0])+buf_.size())); \ BOOST_PP_REPEAT(n, OSTREAM_ARRAY_ASSIGNMENT, ~) \ } #define BOOST_PP_LOCAL_LIMITS (1, BOOST_PP_EXPAND(ARGUMENT_MAX_COUNT)) /* 複数のostreamへ出力するためのstreambufクラス */ template <class Ch, class Tr=std::char_traits<Ch> > class basic_multi_streambuf : public std::basic_streambuf<Ch,Tr> { public: typedef typename std::basic_streambuf<Ch, Tr>::int_type int_type; #include BOOST_PP_LOCAL_ITERATE() void add(std::basic_ostream<Ch, Tr>& os) { outs_.push_back(&os); } ~basic_multi_streambuf() {} protected: int_type overflow(int_type c=Tr::eof()) { if(c!=Tr::eof()) { const size_t pos = pptr()-pbase(); if(buf_.size() <= pos+1) { buf_.resize(2*buf_.size()); setp(&(buf_[0]), (&(buf_[0])+buf_.size())); pbump(pos); } *pptr() = Tr::to_char_type(c); pbump(1); return Tr::not_eof(c); } return Tr::eof(); } int sync() { const size_t pos = pptr()-pbase(); for(ostreams::iterator it=outs_.begin(); it!=outs_.end(); ++it) { (*it)->write(&(buf_[0]), pos); (*it)->flush(); } pbump(pbase()-pptr()); return 0; } private: explicit basic_multi_streambuf<Ch, Tr>(const basic_multi_streambuf<Ch, Tr>&); basic_multi_streambuf<Ch, Tr> &operator=(const basic_multi_streambuf<Ch, Tr>&); typedef std::vector<std::basic_ostream<Ch,Tr>* > ostreams; ostreams outs_; std::vector<Ch> buf_; }; #define BOOST_PP_LOCAL_MACRO(n) \ basic_multi_ostream(BOOST_PP_ENUM_PARAMS(n, std::basic_ostream<Ch BOOST_PP_COMMA() Tr>& os)) \ : std::basic_iostream<Ch,Tr>(&streambuf_), streambuf_(BOOST_PP_ENUM_PARAMS(n, os)) \ {} #define BOOST_PP_LOCAL_LIMITS (1, BOOST_PP_EXPAND(ARGUMENT_MAX_COUNT)) /* 複数のostreamへ出力するためのラッパークラス */ template <class Ch, class Tr=std::char_traits<Ch> > class basic_multi_ostream : public std::basic_iostream<Ch,Tr> { public: #include BOOST_PP_LOCAL_ITERATE() ~basic_multi_ostream() {} void add(std::basic_ostream<Ch, Tr>& os) { streambuf_.add(os); } private: explicit basic_multi_ostream(const basic_multi_ostream&); basic_multi_ostream &operator=(const basic_multi_ostream&); basic_multi_streambuf<Ch, Tr> streambuf_; }; } typedef detail::basic_multi_ostream<char> multi_ostream; typedef detail::basic_multi_ostream<wchar_t> multi_wostream; #undef ARGUMENT_MAX_COUNT #undef OSTREAM_ARRAY_ASSIGNMENT } #endif }}

表示オプション

横に並べて表示:
変化行の前後のみ表示:
目安箱バナー