3

(演習として) C++ で単純な数値範囲クラスを作成しようとしています。等間隔の double を反復処理できます ( numpy/Python のようにarange):

私がやりたいこと(ただし、イテレータを使用):

double lower = ..., upper = ..., delta = ...;
for (double val = lower; val < upper; val += delta)
{
   // do something with val
   f(val);
}
// include the last val to guarantee upper is included or exceeded
f(val); // do something with val

必要な同等の反復子コード:

double lower = ..., upper = ..., delta = ...;
NumericRange nr(lower, upper, delta);
for (NumericRange::const_iterator iter = nr.begin(); iter != nr.end(); iter++)
{
    f(*iter);
}

コードを再利用できるように、イテレーターを STL イテレーターと互換性を持たせたいと考えています (NumericRange を反復することは、std::vector を反復することと同等である必要があります)。

std::vector に値を格納するだけで成功しました (そして、std::vector のイテレータを使用します)。これが、私がオンラインで見つけたすべてがこの問題を解決した方法です。ただし、リスト全体を保存する必要はありません。

値のセット全体を保存しないようにする方法はありますか? を保存せずに目的の効果を得るために、からiterable継承してオーバーライドできるクラスはありますか?++==std::vector<double>

(BOOSTなしでこれを行う方法を本当に知りたいのですが、BOOSTソリューションのようなものを(ゼロから)書く方法を学びたいので、その部分は間違いなく知っていますのソフトウェア エンジニアリングは、他の人が作成したツールを使用していますが、それらのツールがどのように設計および構築されているかを学びたいと思っています)。

私の反復可能な NumericRange クラス (std::vector<double>内部的に使用):

class NumericRange
{
protected:
  double lower, upper, delta;
  std::vector<double> sorted_range;
public:
  typedef std::vector<double>::const_iterator const_iterator;
  NumericRange()
  {
    lower = upper = delta = std::numeric_limits<double>::quiet_NaN();
    // vector is constructed empty
  }
  NumericRange(double lower_param, double upper_param, double delta_param)
  {
    lower = lower_param;

    upper = upper_param;
    delta = delta_param;
    assert(upper_param > lower_param);

    double val;
    // note: can be much faster without push_back
    for (val = lower_param; val < upper_param; val += delta_param)
      {
    sorted_range.push_back(val);
      }
    // ensure the upper_value is contained or surpassed
    sorted_range.push_back(val);
  }
  // to prevent comparison of the entire vector
  bool operator ==(const NumericRange & rhs) const
  {
    return lower == rhs.lower && upper == rhs.upper && delta == rhs.delta;
  }
  // note: this class doesn't really need to store the values in a
  // vector, but it makes the iterator interface much easier.
  const_iterator begin() const
  {
    return sorted_range.begin();
  }
  const_iterator end() const
  {
    return sorted_range.end();
  }
  double get_lower() const
  {
    return lower;
  }
  double get_upper() const
  {
    return upper;
  }
  double get_delta() const
  {
    return delta;
  }
  size_t size() const
  {
    return sorted_range.size();
  }
  void print() const
  {
    std::cout << "[ " << lower << " : " << upper << ": +=" << delta << " ]" << std::endl;
  }
};
4

1 に答える 1

5

を保存せずに目的の効果を得るために、++継承してオーバーライドできる反復可能なクラスはありますか?==std::vector<double>

はいあります。その名はstd::iterator<std::input_iterator_tag, double>

を使用して、ここから始めましょうint。脳内のスペースを節約するために、同じクラスを使用して範囲と反復子の両方を表します。

#include <iterator>
#include <iostream>

struct NumericRange : public std::iterator< std::input_iterator_tag, int >
{
  int current, fini, delta;
  typedef NumericRange iterator;
  typedef iterator const_iterator;
  iterator begin() { return *this; }
  iterator end() { return iterator(fini, fini, delta); }
  iterator& operator++() { current += delta; return *this; }
  iterator operator++(int) { iterator result(*this); ++*this; return result; }
  int operator*() const { return current; }
  NumericRange(int start, int fini, int delta) 
    : current(start), fini(fini), delta(delta)
  {
  }
  bool operator==(const iterator& rhs) {
    return rhs.current == current;
  }
  bool operator!=(const iterator& rhs) {
    return !(*this == rhs);
  }
};

void f(int i, int j) {
  std::cout << i << " " << j << "\n";
}

int main () {
  int lower = 4, upper = 14, delta = 5;
  NumericRange nr(lower, upper, delta);
  for (NumericRange::const_iterator iter = nr.begin(); iter != nr.end(); iter++)
  {
      f(*iter, *nr.end());
  }
}
于 2012-04-14T23:37:02.360 に答える