-
Notifications
You must be signed in to change notification settings - Fork 274
Add ranget drop and skip methods #4347
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
Add ranget drop and skip methods #4347
Conversation
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 PR failed Diffblue compatibility checks (cbmc commit: 73cbe05).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103580996
Status will be re-evaluated on next push.
Common spurious failures:
-
the cbmc commit has disappeared in the mean time (e.g. in a force-push)
-
the author is not in the list of contributors (e.g. first-time contributors).
-
the compatibility was already broken by an earlier merge.
src/util/range.h
Outdated
void drop(std::size_t count) | ||
{ | ||
std::size_t i = 0; | ||
while(i < count && begin_value != end_value) |
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.
Nit pick, but wouldn't this make for a very nice for
loop? As is, it looks a bit like assembler programming.
src/util/range.h
Outdated
/// Return an new range containing the same elements except for the first | ||
/// \p count elements. | ||
/// If the range has fewer elements, returns an empty range. | ||
ranget<iteratort> skip(std::size_t count) 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.
I don't find the names drop
and skip
entirely intuitive. I am wondering whether using longer, more unambiguous names would be better?
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.
Maybe. I'm open to suggestions. drop
is also used by range-v3, so we should maybe keep this one.
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.
Whatever is used elsewhere I'm happy with, just stick with that terminology then.
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.
drop
and skip
are both fine names, but they are kinda synonyms. I think we should choose one or the other, but not both. The name used in .net
's linq is skip
- https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skip?view=netframework-4.7.2
The name in haskell would be drop - http://zvon.org/other/haskell/Outputprelude/drop_f.html
Because C++ supports overloading we could actually have 3 different overloads, all with the same name if we wanted. A mutation overload, a const &
overload and an r-value overload. I would suggest keeping just a const &
and the r-value overload, in order to reduce the need to reason about mutation.
unit/util/range.cpp
Outdated
} | ||
THEN("Skip first 2 elements") | ||
{ | ||
auto range = make_range(list).skip(2); |
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 think it would be better to have a test where you also test the original range to make that indeed skip
does not modify anything, just generates a copy.
73cbe05
to
39146d2
Compare
@smowton I made a slight change to the drop function: by returning a Boolean we can avoid some redundant iterator comparison and for instance write |
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 PR failed Diffblue compatibility checks (cbmc commit: 39146d2).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103603097
Status will be re-evaluated on next push.
Common spurious failures:
-
the cbmc commit has disappeared in the mean time (e.g. in a force-push)
-
the author is not in the list of contributors (e.g. first-time contributors).
-
the compatibility was already broken by an earlier merge.
src/util/range.h
Outdated
/// \return true if the range still contains element after the drop | ||
bool drop(std::size_t count) | ||
{ | ||
for(std::size_t i = 0; i < count; ++i) |
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 don't actually need i
, do you? for( ; count > 0; --count) ...
would do the trick.
ac09326
to
d6b5acb
Compare
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 PR failed Diffblue compatibility checks (cbmc commit: ac09326).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103676521
Status will be re-evaluated on next push.
Common spurious failures:
-
the cbmc commit has disappeared in the mean time (e.g. in a force-push)
-
the author is not in the list of contributors (e.g. first-time contributors).
-
the compatibility was already broken by an earlier merge.
2f9f9e2
to
e6cb484
Compare
/// \return true if the range still contains element after the drop | ||
ranget<iteratort> drop(std::size_t count) && | ||
{ | ||
for(; count > 0 && begin_value != end_value; --count) |
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.
💡 Could this be defined in terms of std::advance
and std::distance
? I think you could advance the begin iterator by the std::min
of count
and the distance between the begin and the end iterators.
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.
Maybe, but I don't know if it's worth it. Some distance functions work by iterating from the current position to the end, so using that plus advance would end up being less efficient.
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 PR failed Diffblue compatibility checks (cbmc commit: 2f9f9e2).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103685752
Status will be re-evaluated on next push.
Common spurious failures:
-
the cbmc commit has disappeared in the mean time (e.g. in a force-push)
-
the author is not in the list of contributors (e.g. first-time contributors).
-
the compatibility was already broken by an earlier merge.
Following @thomasspriggs suggestions, I made the two versions be named |
This is useful for advancing the range without having to manipulate the private `begin_value` field. We have two versions of this, both return a new range, but one is used when the range on which the method is called can be moved.
This tests that these operations behave as expected and gives examples on how to use them.
This can avoid some copies of the iterators.
e6cb484
to
962c9f4
Compare
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.
✔️
Passed Diffblue compatibility checks (cbmc commit: 962c9f4).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/103695677
This adds two utility methods to ranget which I would find useful.
For instance we could iterate on a ranget with a while loop instead of a range-for:
while(!range.empty()) { ....; range.drop(1); ...}