c++ - 我如何编写一个迭代器包装器来组合来自底层迭代器的顺序值组?

标签 c++ iterator

考虑以下顺序:

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

我有那个序列的输入迭代器。我想将这些迭代器包装在生成以下序列的迭代器上:

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

如果不清楚,这个序列是从原始序列开始的连续对连续元素的序列。虽然原始序列有 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;
    };

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

另一个在标有 B 的行上:我保持底层迭代器始终在“当前”对之前,所以如果迭代器在最后一对,则底层迭代器将是结束迭代器,因此比较对结束 pairing_iterator 为真。

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

我是在重新发明一个已经存在于某个地方的轮子吗?我在 Boost 中没有发现这样的东西,这让我有点吃惊。但我很想找到现成的解决方案。

如果这个轮子不在那里,我怎样才能让它真正滚动?

最佳答案

我有两个建议你已经在聊天中否决了,一个有一个奇怪但相对安全的限制,一个有一个丑陋的解决方法来解决这个限制:

第一个想法很简单,但是在每次前进之前只需要一次解引用

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

第二个想法移除了exactly one dereference限制,但是又丑又奇怪:

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

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

关于c++ - 我如何编写一个迭代器包装器来组合来自底层迭代器的顺序值组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11424565/

相关文章:

c++ - 在 C++ Boost 库中,为什么某些头文件上有 ".ipp"扩展名

c++ - 更改任意数字类型值的范围刻度

c++ - 实例化模板参数的参数包

c++ - 处理特定类型元素的任何容器的非模板函数

C++ 在 ‘value_type’ 中没有名为 ‘struct std::iterator_traits<int>' 的类型

c++ - 带有 set 的 std::inserter - 插入到 begin() 或 end()?

c++ - 迭代器的概念问题

c++ - 将两个 Gdiplus::Bitmap 合并为一个 C++

C++ std::vector<std::string> 迭代器段错误

c++ - 如何使用方法 ID 从 Powerbuilder 调用 PBNI 方法