-
Notifications
You must be signed in to change notification settings - Fork 32
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
Reference stability requirements? #101
Comments
I haven't documented this anywhere, but I definitely should, so here we go... For single-pass sequences, there is no reference stability: that is, if you're holding on to a reference to an element returned by For I've previously thought there should be alternative versions of A related question that I haven't quite answered yet is about cursor invalidation, specifically, if I have a valid cursor (I think we do need to require that given |
I don't think you can do that in general? Especially if you're providing an adapter from a C++ range to a sequence, since there's definitely no guarantee that an iterator is still valid through a move. |
The particular example I had in mind was a template <multipass_sequence Seq>
auto rotate(Seq seq, cursor_t<Seq> mid) -> multipass_sequence auto; This is a relatively easy adaptor to write: we iterate from |
Having pondered it some more, I think that having auto elem = flux::min(get_vector()); // assume this returns optional<element_t>
if (elem.has_value()) { // engaged if source vec was non-empty
do_stuff(*elem); // uh-oh
} Instead I think it would be better to have a more direct equivalent of template <multipass_sequence Seq, typename Cmp = std::ranges::less>
auto find_min(Seq&& seq, Cmp cmp = {}) -> cursor_t<Seq>
{
auto min = first(seq);
if (is_last(seq, min)) {
return min;
}
for (auto cur = next(seq, min); !is_last(seq, cur); inc(seq, cur)) {
if (invoke(cmp, read_at(seq, cur), read_at(seq, min)) {
min = cur;
}
}
return min;
} We could also potentially optimise |
Downside of Certainly true that returning a cursor is safer. |
If I have a
sequence
whoseelement
type isT&
, are there any rules around what the lifetime of that reference needs to be? Specifically, is this necessary valid:One motivation for this question is how to do algorithms. Like
min
is currentlyflux/include/flux/op/minmax.hpp
Lines 23 to 37 in 87b50c5
where
fold_first
isflux/include/flux/op/fold.hpp
Lines 36 to 59 in 87b50c5
What this means is that if I have a sequence where
value=string
andelement=string const&
, and I'm finding the minimum string, the worst-case scenario (the sequence is perfectly sorted, backwards) is that I'm doing N string copies. But in this case, if references were guaranteed/required stable, you could do a much more efficient approach via this:This does zero string copies. Basically, this is
min_element
instead ofmin
. This version returns an optional reference, but an equivalent that returns an optional value would still be better since it does exactly 1 string copy.So I guess the question is:
If NO, then we probably want a version of
fold_first
that returnsoptional<element>
instead ofoptional<value>
. Possibly up to even havingfold_first
itself just only ever returnoptional<element>
(which is what it does in Rust 1) or possibly have the callable required to either returnvalue
orelement
and return accordingly.If YES, then... I guess no further work necessary, but probably should be noted somewhere regardless.
Footnotes
Rust originally called it
fold_first
, which I thought was a good name, so that's what I named our version of the algorithm for C++23, then they rename it toreduce
. Jerks. ↩The text was updated successfully, but these errors were encountered: