Multi-step iterators using coroutines.

I wanted to turn this multi-step iteration function into an iterator:

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.

Advertisements
Aside | This entry was posted in Programming and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s