9

次のシーケンスを検討してください。

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

そのシーケンスの入力イテレータがあります。代わりに、次のシーケンスを生成するイテレーターでこれらのイテレーターをラップしたいと思います。

(1,2), (3,4), (5,6), (7,8), (9,10)

明確でない場合、このシーケンスは、元の要素からの連続した要素の連続したペアのシーケンスです。オリジナルには 10 個の要素がありますが、これには 5 個あります。各要素は、元のシーケンスの 2 つから取得されます。

これを実装するためにBoostを使用しiterator_facadeていますが、これを間違って試みています:

    template <typename Iterator>
    struct pairing_iterator
    : boost::iterator_facade<
        pairing_iterator<Iterator>,
        std::array<typename std::iterator_traits<Iterator>::value_type, 2>,
        std::input_iterator_category
        // I should probably customize reference too, but it's not relevant
    > {
        pairing_iterator(Iterator it) : it(it) {
            increment(); // A
        }
        pairing_iterator::value_type dereference() const {
            return pair;
        }
        bool equal(pairing_iterator const& that) const {
            return it == that.it; // B
        }
        void increment() {
            pair = { { *it++, *it++ } };
        }
        Iterator it;
        pairing_iterator::value_type pair;
    };

私が直面している問題の 1 つは、A でマークされた行にあります。渡されたイテレータが終了イテレータの場合、インクリメントが発生しますが、これはできません。

もう 1 つは B でマークされた行にあります。基になるイテレータを常に「現在の」ペアより前に保持しているため、イテレータが最後のペアにある場合、基になるイテレータは終了イテレータになり、true とpairing_iterator を終了します。

基礎となる反復子がforward iteratorの場合、逆参照のたびに単純にペアを読み取り、インクリメントで単純に 2 回進めることができます。しかし、入力反復子を使用すると、一度しか読み取ることができません。

どこかにすでに存在する車輪を再発明しているのでしょうか? Boost ではこのようなものは見つかりませんでした。これには少し驚きました。しかし、私は既成の解決策を見つけたいと思っています。

この車輪がまだ出ていない場合、どうすれば実際に転がすことができますか?

4

2 に答える 2

1

私はあなたが既にチャットで削除した 2 つの提案を持っています。

最初のアイデアは非常に単純ですが、前進する前に 1 つの逆参照が必要です

template <typename Iterator>
struct pairing_iterator
: boost::iterator_facade<
    pairing_iterator<Iterator>,
    std::array<typename std::iterator_traits<Iterator>::value_type, 2>,
    std::input_iterator_category
    // I should probably customize reference too, but it's not relevant
> {
    pairing_iterator(Iterator it) : it(it) {
    }
    pairing_iterator::value_type dereference() const {
        auto t = *it++;
        return { { std::move(t), *it } };
    }
    bool equal(pairing_iterator const& that) const {
        return it == that.it;
    }
    void increment() {
        ++it;
    }
    Iterator it;
};

2番目のアイデアは、逆参照の制限を1つだけ取り除きますが、見苦しく奇妙です:

template <typename Iterator>
struct pairing_iterator
: boost::iterator_facade<
    pairing_iterator<Iterator>,
    std::array<typename std::iterator_traits<Iterator>::value_type, 2>,
    std::input_iterator_category
    // I should probably customize reference too, but it's not relevant
> {
    pairing_iterator(Iterator it) : it(it), dereferenced(false) {
    }
    pairing_iterator::value_type dereference() const {
        if (!dereferenced) {
            auto t = *it++;
            pair = { { std::move(t), *it } };
            dereferenced = true;
        }
        return pair;
    }
    bool equal(pairing_iterator const& that) const {
        return it == that.it;
    }
    void increment() {
        if (!dereferenced)
            dereference();
        dereferenced = false;
        ++it;
    }
    Iterator it;
    pairing_iterator::value_type pair;
    bool dereferenced;
};

おそらくいくつかの間違いを犯したと思いますが、コンセプトを説明するにはこれで十分だと思います。

于 2012-07-11T03:24:59.753 に答える
-1
template<typename T>
struct piterator {
   typedef std::pair<typename std::iterator_traits<T>::value_type,
                     typename std::iterator_traits<T>::value_type> value_type;

   piterator(){}
   piterator( const T& t, const T& e):itr(t),eitr(e){
     if( itr != eitr ) head.first = *itr;
     if( itr != eitr )head.second = *(++itr);
   }
   bool operator ==( const piterator& e )const {
      return e.itr == itr && e.eitr== eitr;
   }

   value_type& operator*(){ return head; }
   const value_type& operator*()const { return head; }
   value_type& operator->(){ return head; }
   const value_type& operator->()const { return head; }

   piterator& operator++() {
      if( itr != eitr )head.first = *(++itr);
      if( itr != eitr )head.second = *(++itr);
      return *this;
   }
   piterator& operator++(int) {
      if( itr != eitr )head.first = *(++itr);
      if( itr != eitr )head.second = *(++itr);
      return *this;
   }
   private:
   T itr;
   T eitr;
   value_type head;
};

ペアリング イテレータが奇数サイズのリストの「末尾を超えていない」ことを確認するには、追加のチェックが必要です。

于 2012-08-03T16:54:19.863 に答える