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.