Boost logo

Boost Users :

From: Keith Bennett (kanezor_at_[hidden])
Date: 2022-05-11 13:54:29


I want to iterate over every point within a geometry::model::box<point>. I
want to be able to do that with iterators so that I can also use all (or
most of) the standard algorithms like for_each or all_of or etc.

Initially my code used several loops, one for each axis, like so for a 2d
point:

for (int x = box.min_corner().template get<0>(); x <=
box.max_corner().template get<0>(); ++x) {
  for (int y = box.min_corner().template get<1>(); y <=
box.max_corner().template get<1>(); ++y) {
    callback(point(x,y))
  }
}

There are several places where this occurs. Some loops have the x axis
first, others the y axis first -- and this has performance issues when
translating the point to a container. Some loops were erroneously
considering right-open intervals with less-than instead of
less-than-or-equal-to comparisons. So I've had to fix bounding bugs and
performance issues in multiple places that are caused by these manual loops.

I've gone and unified a lot of that to use templated functions that
basically duplicate some of the functionality in the standard. But that's
not tractable and still doesn't use iterators so most of <algorithm> is
still off-limits:

namespace mynamespace {
template <class box, enable_if vomit, blah blah>
void for_each(const box& b, const std::function<void(const typename
box::point_type&)> callback) {
    // the manual loops here, not repeated for brevity
}
}

Then I've replaced most of those manual loops with calls to:

mynamespace::for_each(box, [](const point& p){
  // do some work here
});

So I want to instead do:

for (const auto& point : box) {
    callback(point);
}

Satisfying that would make a lot of places simpler and easier to read. I
think it should also help to enable use of a lot of the stuff in the
standard <algorithm>

I understand that it might be difficult for, eg, a box containing a point
with floating point types. But that's fine ... I'm only looping over
integral points anyway.

I'd also prefer to have the ability to control the axis order ... eg do I
want x or y on the inner/outer loop? Do I want to only iterate over the y
axis?

I'm using C++14 and boost 1.70 at the moment. There's some friction against
upgrading. But if this problem is solved in a future version -- like with
C++20 ranges -- then that would be a strong point for me to convince my
team to upgrade.

I could go and write up some iterators myself of course. But before I do
that I wondered if someone else has already solved this problem and I just
haven't found the solution. Thoughts?

-- 
Keith Bennett


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net