C++ Multi-step iterators using coroutines

(Article from 2014)

I wanted to turn this multi-step iteration function into an iterator, so that I could simply use operator++ to advance it:

template<typename Func>
void iterate_edges(rect r, Func func = Func())
{
    coord current = r.c;
    for(;current.x < r.rx(); ++current.x)
        func(current);
    for(;current.y < r.ry(); ++current.y)
        func(current);
    for(;current.x > r.c.x; --current.x)
        func(current);
    for(;current.y > r.c.y + 1; --current.y)
        func(current);
}

It turns out that it can be done very simply using boost::asio::coroutine:

rect_edge_iterator& rect_edge_iterator::operator++()
{
    reenter(m_coro)
    {
        while(m_current.x < m_rect.rx())
        {
            ++m_current.x;
            yield return *this;
        }
        while(m_current.y < m_rect.ry())
        {
            ++m_current.y;
            yield return *this;
        }
        while(m_current.x > m_rect.c.x)
        {
            --m_current.x;
            yield return *this;
        }
        while(m_current.y > m_rect.c.y + 1)
        {
            --m_current.y;
            yield return *this;
        }
        --m_current.x; // change to an 'end' position
    }
    return *this;
}

I thought that was kind of neat. It’s not very often I find a practical use of stackless coroutines in C++.

Note: This only works cleanly for forward iterators.

[More programming articles] [Back to my homepage]