任意のイテレータを抽象型にラップするイテレータを書く話

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;
}