バグ取りとかメンバの追加とか
ここ数日の検討結果をコードに反映させました。
日記に書いてない変更で大きなところは、multiplexer/demultiplexerのcomponent()メソッドでしょうか。
class multiplexer_impl { public: template<typename Source> void push(const Source& src, std::streamsize elm_size); template<typename T> const T* component(int n) const; private: boost::ptr_vector<muxer_component_base> sources_; };
push()で任意のSourceを追加可能で、component()は追加したときの型でSourceを取り出せます。boost::iostreams::chainのそれとほぼ同じです。
実装もほぼ同じで、
class muxer_component_base { public: virtual ~muxer_component_base() {} virtual std::streamsize read(char* s, std::streamsize n) = 0; virtual void close() = 0; }; template<class Source> class muxer_component : public muxer_component_base { // 略 }; template<typename Source> void multiplexer_impl::push(const Source& src, std::streamsize elm_size) { sources_.push_back(new muxer_component<Source>(src, elm_size)); } template<typename T> const T* multiplexer_impl::component(int n) const { typedef muxer_component<T> wrapper; if (const wrapper* ptr = dynamic_cast<const wrapper*>(&sources_[n])) return ptr->component(); else return 0; }
個々のSourceに継承関係はなくとも、即席で(ラッパークラスを通して)継承関係を作ってしまうので、dynamic_castで復元できるわけです。Boost.Anyと同じカラクリです。