4

範囲ベースのループを使用して、STL コンテナー内のアイテムの連続するペアをループするカスタム クラスを作成するにはどうすればよいですか?

これは私が望む構文と出力です:

std::list<int> number_list;
number_list.push_back(1);
number_list.push_back(2);
number_list.push_back(3);

auto paired_list = Paired(number_list);
for (const auto & pair : paired_list) {
  std::printf("The pair is (%d, %d)\n", *(pair[0]), *(pair[1]));
  // or
  //std::printf("The pair is (%d, %d)\n", *(pair.first), *(pair.second));
}
// output:
// The pair is (1, 2)
// The pair is (2, 3)

これら(およびそれ以上)が必要であることは知っていますが、わかりません:

template <class T>
class Paired {
  ???
  class iterator {
    ???
  }
  iterator begin() {
    ...
  }
  iterator end() {
    ...
  }
}

const修飾子について心配する必要はありません。

ブーストなし。

コンテナー内のオブジェクトを変更またはコピーしないでください。

4

4 に答える 4

3

編集私が使用してtransformいた。

を使用しadjacent_differenceます。

2番目のバージョンは、2つの値を新しい(異なる)値に変換するバイナリ関数を取ります。

string make_message(int first, int second) {
    ostringstream oss;
    oss << "The pair is (" << first << ", " << second << ")";
    return oss.str();
}

これで、隣接するペアを3番目の範囲に変換できます。を使用して、範囲のようostream_iteratorに使用します。cout

list<int> numbers;
//...
adjacent_difference(numbers.begin(), numbers.end(),
                    ostream_iterator<string>(cout, "\n"),
                    make_message);

2回目の編集

comp.lang.c ++。moderatedで、。などの標準ライブラリに「隣接する」関数がこれ以上ない理由を尋ねる質問を見つけましたfor_each_adjacent。返信では、を使用して実装するのは簡単であると述べていstd::mismatchます。

これは、特別な隣接イテレータを実装するよりも良い方向だと思います。

于 2013-02-12T07:57:43.863 に答える
0

これを試して。

#include <list>
#include <iostream>

template<class T, class TIter = typename T::iterator, class TVal = typename T::value_type>
class PairedImpl {
    T& m_t;
public:
    class Iter {
        TIter m_it;
    public:
        Iter(const TIter & it) : m_it(it)  {}

        bool  operator!=(const Iter& it)   {         return m_it != it.m_it; }
        Iter& operator++()                 { ++m_it; return *this; }
        const Iter & operator *() const    {         return *this; }
        const TVal & first()      const    {         return *m_it; }
        const TVal & second()     const    {         return *std::next(m_it); }
    };

    PairedImpl(T& t) : m_t(t) {}

    Iter begin() { return Iter(m_t.begin()); }

    Iter end() {
        TIter end = m_t.end();
        return Iter(m_t.empty() ? end : --end);
    }
};

template<class T>
PairedImpl<T> Paired(T& t) {
    return PairedImpl<T>(t);
}

使用法

int main()
{
    std::list<int> lst;
    lst.push_back(1);
    lst.push_back(2);
    lst.push_back(3);
    lst.push_back(4);
    lst.push_back(5);

    for (const auto & pair : Paired(lst)) {
        std::cout << "(" << pair.first() << ", " << pair.second() << ")" << std::endl;
    }
    return 0;
}
于 2013-02-12T08:46:39.600 に答える
-1

さて、答えのない1時間、私はうまくいく解決策を思いつきました. FixedLengthVectorこれは、まさにそのように聞こえる私自身のものを使用していることに注意してください。

template <class T>
class Grouped {
private:
  // length of grouped objects
  static const unsigned length_ = 2;
  // hold pointer to base container to avoid comparing incompatible iterators
  T * base_container_;
public:
  // constructor
  Grouped(T & base_container) :
      base_container_(&base_container) {
  }
  // iterator
  class iterator {
  private:
    // hold pointer to base container to avoid comparing incompatible iterators
    T * base_container_;
    // hold pointers to objects in base container
    FixedLengthVector<length_, typename T::value_type *> ptr_;
    // hold iterator to last object
    typename T::iterator last_iterator_;
  public:
    // constructor
    iterator(T & base_container, typename T::iterator & it)
        : base_container_(&base_container),
          last_iterator_(it) {
      // set up pointers if possible
      unsigned i = 0;
      // check for end iterator
      if (last_iterator_ == base_container_->end()) {
        ptr_.fill(NULL);
        return;
      }
      // set up first object
      ptr_[0] = &*last_iterator_;
      // set up next objects
      for (unsigned i = 1; i < length_; ++i) {
        ++last_iterator_;
        if (last_iterator_ == base_container_->end()) {
          ptr_.fill(NULL);
          return;
        }
        ptr_[i] = &*last_iterator_;
      }
    }
    // dereference operator
    FixedLengthVector<length_, typename T::value_type *> & operator * (void) {
      assert(ptr_[0] != NULL);
      return ptr_;
    }
    // pre-increment
    iterator & operator ++ (void) {
      // can't increase past end
      assert(last_iterator_ != base_container_->end());
      // find next iterator
      ++last_iterator_;
      if (last_iterator_ == base_container_->end()) {
        ptr_.fill(NULL);
        return * this;
      }
      // cycle pointers left
      for (unsigned i = 1; i < length_; ++i) {
        ptr_[i - 1] = ptr_[i];
      }
      ptr_[length_ - 1] = &*last_iterator_;
      return * this;
    }
    // equality comparison
    bool operator == (const iterator & that) const {
      return base_container_ == that.base_container_ &&
             last_iterator_ == that.last_iterator_;
    }
    // inequality comparison
    bool operator != (const iterator & that) const {
      return !(*this == that);
    }
  };
  // end iterator
  iterator end() {
    return iterator(*base_container_, base_container_->end());
  }
  // begin iterator
  iterator begin() {
    return iterator(*base_container_, base_container_->begin());
  }
};
于 2013-02-12T08:01:10.943 に答える