任意のイテレータを抽象型にラップするイテレータを書く話
C++ で仮想メンバ関数テンプレートを使いたい - kazuhoのメモ置き場の件、id:moriyoshi さんからトラックバックをいただきました。ありがとうございます。
それにしてもこの 2 つは本当に水と油だね。typeinfo 見てディスパッチする、というのがばっちりはまる場合というのも結構ありそうだけど、今回は「2 つのイテレータで表される range を受け取るテンプレート関数を仮想関数にしたい」というような状況に限定して考えてみる。
テンプレートメンバ関数と仮想関数を (半ば強引に) 組み合わせる - muddy brown thang
イテレータの操作を仮想関数にして良いのであれば、以下のように書けば、きれいのではないかと思いました (const_iter とか traits は省略)。なんで boost にないんだろ。って、boost:any_iterator てのがあるのかな。
#include <iostream> #include <list> #include <vector> template <typename T> class any_iter; template <typename T> class any_iter_impl_base_t { public: typedef T value_type; friend class any_iter<T>; protected: virtual ~any_iter_impl_base_t() {} virtual any_iter_impl_base_t* clone() = 0; virtual value_type* get() = 0; virtual const value_type* get() const = 0; virtual void incr() = 0; virtual bool eq(const any_iter_impl_base_t* x) const = 0; }; template <typename Iter> class any_iter_impl_t : public any_iter_impl_base_t<typename Iter::value_type> { public: typedef typename Iter::value_type value_type; protected: typedef any_iter_impl_base_t<value_type> super; Iter iter_; public: any_iter_impl_t(const Iter& iter) : iter_(iter) {} protected: virtual super* clone() { return new any_iter_impl_t(iter_); } virtual value_type* get() { return &*iter_; } virtual const value_type* get() const { return &*iter_; } virtual void incr() { iter_++; } virtual bool eq(const super* x) const { assert(typeid(*x) == typeid(any_iter_impl_t<Iter>)); return iter_ == static_cast<const any_iter_impl_t<Iter>*>(x)->iter_; } }; template <typename T> class any_iter { public: typedef T value_type; protected: any_iter_impl_base_t<T>* impl_; public: template <typename Iter> any_iter(const Iter& iter) : impl_(new any_iter_impl_t<Iter>(iter)) {} any_iter(const any_iter& x) : impl_(x.impl_->clone()) {} ~any_iter() { delete impl_; } any_iter& operator=(const any_iter& x) { if (this != &x) { delete impl_; impl_ = x.impl_->clone(); } return *this; } value_type* operator->() { return impl_->get(); } const value_type* operator->() const { return impl_->get(); } value_type& operator*() { return *operator->(); } const value_type& operator*() const { return *operator->(); } any_iter& operator++() { impl_->incr(); return *this; } any_iter operator++(int) { any_iter r(this->impl_->clone()); impl_->incr(); return r; } bool operator==(const any_iter& x) const { return impl_->eq(x.impl_); } bool operator!=(const any_iter& x) const { return ! operator==(x); } }; static int sum(const any_iter<int>& first, const any_iter<int>& last) { int r = 0; for (any_iter<int> i = first; i != last; ++i) { r += *i; } return r; } int main(void) { std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); std::cout << sum(v.begin(), v.end()) << std::endl; std::list<int> l; l.push_back(4); l.push_back(5); l.push_back(6); std::cout << sum(l.begin(), l.end()) << std::endl; return 0; }