-
Notifications
You must be signed in to change notification settings - Fork 219
use auto instead of iterator types, and related #1129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use auto instead of iterator types, and related #1129
Conversation
it = boost::begin(multi); | ||
it != boost::end(multi); | ||
++it) | ||
for (auto it = boost::begin(multi); it != boost::end(multi); ++it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NOTE: we cannot do a range based for loop here
(as @awulkiew pointed out once).
In some places I changed it to a range based for loop, but these places are internal (for example turns).
point_t const& p0 = *prev; | ||
point_t const& p1 = *it; | ||
auto const& p0 = *prev; | ||
auto const& p1 = *it; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that here iterator could return non-true reference type. Previously this type was converted to point_t
which was value_type vs reference_type returned by iterator. If this non-true reference type was not adapted to Point concept the call to convert below could fail to compile. I don't know if that's a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your comments! I'll process them soon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure either. Reverted (it was not related to the iterator anyway)
✔️
@@ -791,7 +775,7 @@ struct buffered_piece_collection | |||
{ | |||
BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u); | |||
|
|||
typename Range::const_iterator it = boost::begin(range); | |||
auto it = std::cbegin(range); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To double-check, is std
intended here? boost::size
is called above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverted. First I changed some begin
but later decided it's better to limit this to iterators only. This was a left over.
✔️
Unless there are objections, a separate PR could change boost::begin
to std::begin
everywhere (+end
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did some more checks, we can't change it everywhere. Because we support geometries adapted to Boost.Range, but not std::begin
etc.
We might (ever) change that, but that might break behavior for users having custom geometries.
// Update member used | ||
turn.turn_index = index; | ||
turn.turn_index = index++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for_each_with_index
is used below. Would it make sense to use it here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's currently a const version only.
But I can add an overload.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
@@ -36,7 +36,7 @@ struct clean_point | |||
, m_is_azi_valid(false), m_is_azi_diff_valid(false) | |||
{} | |||
|
|||
typename boost::iterators::iterator_reference<Iter>::type ref() const | |||
auto ref() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This way the reference will be converted to value. The function should probably return decltype(auto)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ reverted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, revert was not required. Returning decltype(auto)
would be enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ intuitively it looked the same, but I get it now. Changed. Thank you.
it = boost::begin(geometry); | ||
it != boost::end(geometry); | ||
++it) | ||
for (auto const& geometry : multi) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Range-based for loop is probably incorrect here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ right, reverted
for (iterator_type it = boost::begin(range_of_boxes); | ||
it != boost::end(range_of_boxes); | ||
++it) | ||
for (auto const& box : range_of_boxes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it's true that currently this function is used only internally I wouldn't be so eager to replace this loop with range-based version. It's because technically we could introduce MultiBox concept in the future. In general I propose to leave normal loops in algorithms taking ranges as template parameters as if they were geometries because replacing them may have unintended consequences for users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ good point, reverted (keeping box
)
typename boost::range_reverse_iterator | ||
< | ||
View const | ||
>::type prev = find_different_from_first(boost::rbegin(view), | ||
boost::rend(view), | ||
strategy); | ||
|
||
iterator next = find_different_from_first(cur, boost::end(view), | ||
strategy); | ||
auto next = find_different_from_first(cur, boost::end(view), strategy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're loosing information here. Previously a reader was able to see that next
was indeed an iterator. However now we don't know what it is. It might be a point or an iterator or something else. I'm thinking about a rule to always have it
in the name for auto
iterators. So cur_it
and next_it
. Does it make sense?
EDIT: btw, I'm not sure if that's a good idea. ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We often use next
. The code currently does not use next_it
.
I kept it here.
But I missed the one on line 80/78 earlier, that's done now ✔️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have it_min
though. So it_next
would work. But I didn't change it, we can consider what we should do in general.
std::size_t counter(0); | ||
do | ||
{ | ||
++counter; | ||
iterator next = std::find_if(current, end, [&](auto const& pt) { | ||
auto next = std::find_if(current, end, [&](auto const& pt) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though here the names doesn't bother me because I can see what they are from the context.
geometry::envelope(get_ring<tag1>::apply(it->first, geometry1), | ||
item.envelope, strategy); | ||
geometry::envelope(get_ring<tag1>::apply(pair.first, geometry1), | ||
item.envelope, strategy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation was changed. Was it intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, no it was not intentional. ✔️
{ | ||
if (index != index_positive) | ||
{ | ||
ring_info_type& inner = ring_map[it->id]; | ||
ring_info_type& inner = ring_map[item.id]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, why have you left ring_info_type
? Not that I'm against it becasue I think that auto
should be used carefully and only if it improves readability. I'm just curious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed using auto is delicate. For iterators it's perfect. If it saves type definitions, I'm also inclined to use it.
In this case it would not save that type.
for_each_with_index(turns, [](auto index, auto const& turn) | ||
{ | ||
debug_follow(turn, turn.operations[0], index); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The indentation is inconsistent with other calls. Besides we should probably mimic loops as it is correctly done in other places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
for (auto it = boost::begin(forward_range); | ||
it != boost::end(forward_range); | ||
++it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to put the loop in one line? It should be lesser than 100 characters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it fits.
✔️
@@ -305,7 +304,7 @@ inline bool calculate_from_inside(Geometry1 const& geometry1, | |||
std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2; | |||
// TODO: the following function should return immediately, however the worst case complexity is O(N) | |||
// It would be good to replace it with some O(1) mechanism | |||
range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2), | |||
auto qk_it = find_next_non_duplicated(boost::begin(range2), | |||
range::pos(range2, q_seg_jk), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation should probably be changed as well.
// search for the entry point in the same range of other geometry | ||
point_iterator entry_it = std::find_if(m_other_entry_points.begin(), | ||
auto entry_it = std::find_if(m_other_entry_points.begin(), | ||
m_other_entry_points.end(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation should probably be changed as well.
for ( ; it != last ; ++it ) | ||
auto it = boost::begin(multi_point); | ||
auto last = boost::end(multi_point); | ||
for ( ; it != last ; ++it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These iterators could probably be put inside the loop. At least it
because with last
/end
there could be a debate about performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ fixed and renamed last
to end
as done elsewhere
{ | ||
typename boost::range_reference<MultiLinestring const>::type | ||
ls = *it; | ||
auto ls = *it; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would cause a linestring to be copied. auto const&
should probably be used here instead.
It's an issue preventing me to approve the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 well spotted, thanks
✔️ changed to auto const&
and a few lines later (for points) as well.
for ( iterator it = boost::begin(geometry::interior_rings(geometry2)) ; | ||
it != boost::end(geometry::interior_rings(geometry2)) ; | ||
++it ) | ||
auto&& rings2 = geometry::interior_rings(geometry2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIU the intention is to represent const reference (even if non-true temporary), not forwarding/universal reference so auto const&
would probably be more appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied this from https://github.com/boostorg/geometry/blob/develop/include/boost/geometry/algorithms/correct.hpp#L135
but indeed, it's not const there.
Changed to auto const&
, indeed we use that more often
for ( iterator2 it = boost::begin(geometry::interior_rings(geometry2)) ; | ||
it != boost::end(geometry::interior_rings(geometry2)) ; | ||
++it ) | ||
auto&& rings2 = geometry::interior_rings(geometry2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ fixed
for ( iterator1 it1 = boost::begin(geometry::interior_rings(geometry1)) ; | ||
it1 != boost::end(geometry::interior_rings(geometry1)) ; | ||
++it1 ) | ||
auto&& rings1 = geometry::interior_rings(geometry1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ fixed
typename interior_return_type<Polygon>::type | ||
rings = interior_rings(poly); | ||
|
||
auto&& rings = interior_rings(poly); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forwarding reference, are we planning to forward rings
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here it is a non-const.
So I changed it like done in correct
.
Maybe auto&
is better in this case, changed it to that. I think that's OK here, @awulkiew ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, if it's non-const then we have to use auto&&
. If we use auto&
the lifetime of a temporary which might be returned by interior_rings()
will not be extended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
rings = interior_rings(polygon); | ||
for (typename detail::interior_iterator<Polygon const>::type | ||
rit = boost::begin(rings); rit != boost::end(rings); ++rit) | ||
auto&& rings = interior_rings(polygon); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forwarding reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ fixed
|
||
for (typename detail::interior_iterator<Polygon const>::type | ||
it = boost::begin(rings); it != boost::end(rings); ++it) | ||
auto&& rings = interior_rings(poly); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention here is to represent const reference, not forwarding reference. auto const&
should probably be used here instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a big PR. Thanks!
I see some minor issues and one preventing me to approve it, i.e. unintended copy of a linestring. There is also unintended copy of a point but that's not that big of a problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM in general with some (minor) comments.
|
||
for (typename detail::interior_iterator<Polygon const>::type | ||
it = boost::begin(rings); it != boost::end(rings); ++it) | ||
auto&& rings = interior_rings(poly); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be more specific here using auto const &
since rings are not modifiable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 ✔️ fixed
for (typename detail::interior_iterator<Polygon const>::type | ||
it = boost::begin(rings); it != boost::end(rings); ++it) | ||
auto&& rings = interior_rings(poly); | ||
auto const end = boost::end(rings); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason of copying here and not just using it as boost::end(rings)
inside for loop as you are doing below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's done elsewhere as well, for rings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is the reason but the effect is that end will not be calculated at the end of each iteration.
iterator_t it = boost::begin(rng); | ||
iterator_t end = boost::end(rng); | ||
auto it = boost::begin(rng); | ||
auto end = boost::end(rng); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it better to declare it as auto const
or even auto const&
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You see it occasionally, but usually iterators are never declared const.
I would not make them auto const&
because it's not a reference (though it's syntactically correct)
Edit: fixed, made const
✔️
@@ -801,7 +785,7 @@ struct buffered_piece_collection | |||
add_point(*it); | |||
} | |||
|
|||
for (++it; it != boost::end(range); ++it) | |||
for (++it; it != std::cend(range); ++it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to @awulkiew's comment above on std::cbegin
. Is there an intention to remove dependencies on boost::begin
and boost::end
from this file? If this is the case I think you could also remove the inclusion of the related header files in the beginning of this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 ✔️ reverted
seg_or_box_const_iterator it_min1 = boost::const_begin(seg_or_box_points); | ||
seg_or_box_const_iterator it_min2 = it_min1; | ||
auto pit_min = points_begin(geometry); | ||
auto it_min1 = boost::const_begin(seg_or_box_points); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this and the next one be auto const
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above, we don't have that habit for iterators
Edit: fixed
Edit2: rolled back, it was actually changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defining it as auto const
will prevent us from changing the iterator e.g incrementg it. If that's ok then it could be const
like in case of end/last. Think about a pointer to const (const_iterator
) vs const pointer (auto const
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I changed it where @vissarion requested this. I completely agree now.
But specifically in this case, this iterator is meant to change. It is an iterator pointing to the minimum. So it cannot be made const
here.
@@ -318,7 +301,7 @@ class geometry_to_segment_or_box | |||
{ | |||
distance::creturn_t<MultiPoint, SegmentOrBox, Strategies> cd_min; | |||
|
|||
iterator_type it_min | |||
auto it_min |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it be auto const
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
edit: fixed ✔️
iterator_type it_max = std::max_element(boost::begin(range_of_boxes), | ||
boost::end(range_of_boxes), | ||
latitude_less<max_corner>()); | ||
auto it_min = std::min_element(boost::begin(range_of_boxes), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto const
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
edit: fixed ✔️
iterator_t it = boost::begin(range); | ||
iterator_t end = boost::end(range); | ||
auto it = boost::begin(range); | ||
auto end = boost::end(range); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto const
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
Edit: for end
which is never changed, we actually did it more often. Changed here ✔️
ca00897
to
cb3bc95
Compare
New version is pushed. I'm still doing some checks, adding a unit test which catches those changes in range-based-for-loops (because apparently they did not exist yet for several algorithms), and catches copies. |
typename interior_return_type<Polygon>::type | ||
rings = interior_rings(poly); | ||
|
||
auto& rings = interior_rings(poly); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto& rings = interior_rings(poly); | |
auto&& rings = interior_rings(poly); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ fixed, thanks
std::size_t index = 0; | ||
for (auto it = std::begin(container); it != std::end(container); ++it, ++index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically the type of index should be taken from Container/Range, e.g.: boost::size_type<Container>::type
but I guess in practice std::size_t
will be ok.
Are we sure that this utility will not be used for geometries adapted to Boost.Range Concept?
Would it make sense to use boost::begin
and boost::end
to be safe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️ fixed. While fixing it, I now also use Boost Range's size type
cb3bc95
to
d0bbb2f
Compare
Results are pushed again. The last push also changes some other interior_ring_type occurrences, fixes a bug (concept) and adds two missing include files. |
Second commit adds tests (and fixes related concept). |
auto const exterior = exterior_ring(poly); | ||
auto const rings = interior_rings(poly); | ||
auto const& exterior = exterior_ring(poly); | ||
auto const& rings = interior_rings(poly); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, I changed this last December. We didn't have unit tests catching this.
|
||
// Define a custom class which is only movable and not copiable, and cannot be indexed. | ||
// Its derivatives will be linestring, ring, multi* | ||
// For readability purposes we use the "cnc" abbreviation as "custom_non_copiable" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class originates from all_custom_geometries
but takes it a bit further, making it non-copyable.
For test purposes it has to be indexable, but that's also customized (the library does not see that).
Also the adaptations are more modern (requiring less typedefs, more readable)
Thanks! |
d2f37ca
to
1dda97c
Compare
@vissarion many tests are added, I'll assume you are still OK. I will merge one of the coming days. |
1dda97c
to
1e04cc6
Compare
It's a big PR but quite mechanical