I'm using a boost R-tree (boost version 1.65.1 and C++ 17) to iterate over some 2D points. What I want to do is to perform neighbour searches for each node (so 'detect' neighbouring nodes), do some stuff with the results, and afterwards remove all query result nodes from the r-tree. Then I want to iterate over the remaining nodes and repeat until I reached the end.
The problem now is that modifying the r-tree this way not only may but in my case does invalidate the iterator. This basically results in a never ending for-loop among other problems.
Right now I don't see an other way to solve this than to reset the iterator to begin().
So my question is:
Is there a more elegant way to do this?
The basic code snippet using an r-tree which stores pairs of 2D-points and some number:
for (auto it = someRTree.begin(); it != someRTree.end(); ++it) {
std::vector<std::pair<point, size_t>> results;
// Creating a query box around the current node
bgm::box<point> queryBox(point(bg::get<0>(it->first) - someConst,
bg::get<1>(it->first) - someConst),
point(bg::get<0>(it->first) + someConst,
bg::get<1>(it->first) + someConst));
someRTree.query(bgi::intersects(queryBox), std::back_inserter(results));
// do something with the results
// ...
someRTree.remove(results); // <- This here will invalidate the iterator.
}
Since the query results are going to be removed from the r-tree anyway, I found a solution, which is a little bit simpler. Basically the for loop is transformed into a while loop and the iterator is set at the beginning of each loop iteration to the beginning of the r-tree. This also makes case handling unnecessary which might otherwise be necessary when using a for loop.
However, since I am not really iterating the iterator I could also just use
someRTree.begin()in place of the iteratorit. This is semantically identical. I just left it this way for convenience reasons.Still, I wonder if there is a better solution. When removing elements from STL containers it's possible to get a iterator pointing to the element following the removed one. Something similar in boost could be advantageous. But there you can only return the number of elements which were removed.