如何编写一个迭代器包装器,它结合了底层迭代器的连续值组?

R. *_*des 9 c++ iterator

请考虑以下顺序:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Run Code Online (Sandbox Code Playgroud)

我为该序列输入了迭代器.我想将迭代器包装在生成以下序列的迭代器上:

(1,2), (3,4), (5,6), (7,8), (9,10)
Run Code Online (Sandbox Code Playgroud)

如果不清楚,则该序列是来自原始序列的一系列连续元素的连续元素.虽然原始有10个元素,但是这个元素有5个:每个元素都来自原始序列中的两个.

我正在使用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;
    };
Run Code Online (Sandbox Code Playgroud)

我面临的一个问题是在标记为A的行上:当传入的迭代器是一个结束迭代器时,这将导致它递增,这是我无法做到的.

另一个是在标有B的行上:我保持底层迭代器总是在"当前"对之前,所以如果迭代器在最后一对,底层迭代器将是一个结束迭代器,因此比较真实end pairing_iterator.

如果底层迭代器是一个前向迭代器,我可以在每次取消引用时简单地读取该对,并且只需在增量上前进两次.但是对于输入迭代器,我只能读一次.

我是否重新发明了已经存在的车轮?我在Boost中找不到这样的东西,这让我感到惊讶.但我很想找到一个现成的解决方案.

如果这个轮子不在那里,我怎么能让它实际滚动?

Moo*_*uck 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;
};
Run Code Online (Sandbox Code Playgroud)

第二个想法消除了确切的一个取消引用限制,但丑陋且奇怪:

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;
};
Run Code Online (Sandbox Code Playgroud)

我可能犯了几个错误,但希望这足以描述这些概念。