2012-07-11 22 views
9

xem xét theo trình tự sau:Làm cách nào để viết một trình bao bọc lặp kết hợp các nhóm các giá trị tuần tự từ trình lặp cơ bản?

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

Tôi có lặp đầu vào cho chuỗi đó. Tôi muốn bao quanh các trình vòng lặp đó trên các trình vòng lặp tạo ra chuỗi sau thay vào đó:

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

Nếu không rõ ràng, chuỗi này là một chuỗi các phần tử liên tục liên tục từ nguyên bản. Trong khi bản gốc có 10 phần tử, phần tử này có 5 phần tử: mỗi phần tử thu được từ hai phần tử từ chuỗi gốc.

Tôi đang sử dụng Boost của iterator_facade để thực hiện điều này, và tôi phải nỗ lực sai này tại đây:

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

Một vấn đề tôi phải đối mặt là trên dòng được đánh dấu bằng A: khi iterator thông qua tại là một trình vòng lặp kết thúc, điều này sẽ dẫn đến việc tăng nó, mà tôi không thể làm được.

Đường khác nằm trên dòng được đánh dấu bằng B: Tôi đang giữ trình lặp cơ bản luôn đi trước cặp "hiện tại", vì vậy nếu trình vòng lặp ở cặp cuối cùng, trình lặp cơ bản sẽ là trình lặp kết thúc và do đó so sánh đúng với một cặp kết thúc_iterator.

Nếu trình vòng lặp cơ bản là trình lặp chuyển tiếp, tôi có thể chỉ đọc từng cặp trên dereferencing và chỉ cần tăng gấp đôi số lần tăng. Nhưng với bộ lặp đầu vào Tôi chỉ có thể đọc một lần.

Tôi có đang phát minh lại bánh xe đã tồn tại ở đâu đó không? Tôi đã không tìm thấy bất cứ điều gì như thế này trong Boost, điều làm tôi ngạc nhiên một chút. Nhưng tôi rất muốn tìm một giải pháp làm sẵn.

Nếu bánh xe này chưa được đặt ở đó, tôi có thể làm như thế nào để cuộn?

+0

Theo ý kiến ​​của tôi, điều này tương tự như trình lặp lọc. Tôi cho rằng tốt nhất là có trình vòng lặp chứa trình lặp kết thúc, để xử lý trường hợp chuỗi bất ngờ chứa một số phần tử lẻ. Điều này cũng sẽ giải quyết cả hai vấn đề của bạn (A và B), bởi vì bạn biết nếu đó là một trình lặp kết thúc, và bạn có thể tách biệt việc thực hiện cặp proxy từ việc gia tăng của trình lặp lặp cơ bản. (Tôi không quen thuộc với mặt lặp lặp của Boost, vì vậy tôi không hoàn toàn chắc chắn như thế nào một trong những sẽ dịch này vào Boosteese). –

+0

'Integer dereference()'? –

+0

@David oops, đó là một tạo tác từ tôi 'mua sắm các chi tiết không cần thiết từ ví dụ :) –

Trả lời

1

Tôi có hai gợi ý bạn đã bị bắn hạ trong trò chuyện, một với một lạ nhưng giới hạn tương đối an toàn, và một với một workaround xấu xí cho giới hạn:

ý tưởng đầu tiên là rất đơn giản, nhưng đòi hỏi phải chính xác một dereference trước mỗi trước

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

ý tưởng thứ hai loại bỏ chính xác một giới hạn dereference, nhưng là xấu xí và kỳ lạ:

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

tôi probab ly thực hiện một số lỗi, nhưng hy vọng điều này là đủ để miêu tả các khái niệm.

+0

{{* it ++, * it}}; sẽ trả về cùng một phần tử cho mỗi trường (hoặc không xác định) vì ++ không xảy ra cho đến sau ';' ... – bytemaster

+0

@bytemaster: Tôi không chắc bạn đúng, nhưng chỉ trong trường hợp, tôi đã sửa nó. Đó là một sự thay đổi tầm thường. –

+0

@bytemaster no, thứ tự đánh giá trong '{}' được xác định rõ. –

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

Cần có kiểm tra bổ sung để đảm bảo rằng trình lặp ghép nối không 'vượt qua kết thúc' của danh sách có kích thước lẻ.

+0

Trình kết hợp * cuối * 'trông như thế nào? AFAICT, nó sẽ đơn giản có hành vi không xác định trực tiếp từ hàm tạo. –

Các vấn đề liên quan