This takes two ranges and invokes a predicate on the element-wise pair in the
ranges. It returns true if all the pairs are matching the predicate and the ranges
have the same size.
It is useful with containers that aren't random iterator where we can't check the
sizes in O(1).
Details
- Reviewers
- None
- Commits
- rGb70de61f4806: Add `all_of_zip` to STLExtras
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/include/llvm/ADT/STLExtras.h | ||
---|---|---|
1724 | The name here feels a bit weird. This is essentially just std::ranges::equal/std::equal with special size mismatch behavior. Can we name it something closer to what it would be replaced by? Also, in what situations is the size mismatch result needed (i.e. the llvm::None)? |
llvm/include/llvm/ADT/STLExtras.h | ||
---|---|---|
1724 | I was trying to differentiate between "length mismatch" and "element mismatch", but maybe we don't need to? |
Seems like a bit of a narrow use case combination of two features - is there much missing/a way we could generalize the more general tools so they could be composed easily enough in the cases where the combination is desirable?
The issue is that I think the "expected" way in C++ to have a zip operator that fails when the length mismatch is to use exceptions. I'm not how else to have a range that can fail when iterated on?
Yeah, while keeping the iterator interface (rather than using a different interface, which would then be less composable) and with arbitrary elements (so you can't construct a default/failed object) it's a bit limited.
What about if the range itself was boolean testable (or had some "areBothRangesTraversed" operation or the like) that could be queried (assert-fails if queried early) after the zip has reached the end (and in that case the end would be the end of either range, whichever comes first)?
What about if the range itself was boolean testable (or had some "areBothRangesTraversed" operation or the like) that could be queried (assert-fails if queried early) after the zip has reached the end (and in that case the end would be the end of either range, whichever comes first)?
That's interesting: the range itself is disconnected from the iterator state though, so I don't think you could just query the range.
The best I can think of would be something that would end-up looking like:
auto range = zip(a, b, c); auto it = range.begin(); for (; it != range.end(); ++it) { ... } if (!it.all_equals(range.end()) // bike shed the API name // error
Augment zip_common with a comparator to test for complete equality of the zipped iterators
Ah, yeah, fair enough. Looks OK.
Though I worry about the likely combinatorial expansion of the ultimate API, still - all_of_zip implies the likely existence of none_of_zip and any_of_zip - which admittedly can be defined in terms of one another, so it's not loads of duplication... eh, maybe that's OK then, if they get created.
Carry on!
The name here feels a bit weird. This is essentially just std::ranges::equal/std::equal with special size mismatch behavior. Can we name it something closer to what it would be replaced by? Also, in what situations is the size mismatch result needed (i.e. the llvm::None)?