This is an archive of the discontinued LLVM Phabricator instance.

[ADT] Zip range adapter
ClosedPublic

Authored by bryant on Aug 7 2016, 8:38 PM.

Details

Summary

As discussed with jokereph over IRC a few weeks ago, this augments the STLExtras toolset with a zip iterator and range adapter. Zip comes in two varieties: zip, which will zip to the shortest of the input ranges, and zip_first, which limits its begin() == end() checks to just the first range.

Diff Detail

Repository
rL LLVM

Event Timeline

bryant updated this revision to Diff 67114.Aug 7 2016, 8:38 PM
bryant retitled this revision from to [ADT] Extra STLExtras.
bryant updated this object.
bryant set the repository for this revision to rL LLVM.
bryant updated this revision to Diff 67119.Aug 7 2016, 9:58 PM

clang-formatted to LLVM indentation style.

Generally lacking test coverage, and could consider using std::begin/std::end rather than member begin/end to make sure these algorithms work with arrays and other things without member begin/end.

include/llvm/ADT/STLExtras.h
238–259 ↗(On Diff #67119)

These look like implementation details (& arguably ZipFirst/ZipShortest/Zippy are implementation details too) that should be hidden from the llvm namespace (either as local/nested types or in a 'detail' namespace, etc).

bryant updated this revision to Diff 67452.Aug 9 2016, 7:18 PM

Use a more efficient method of generating the integer sequence. Encase NatList, Zippy, ZipFirst, ZipShortest in their own detail namespace.

bryant marked an inline comment as done.Aug 9 2016, 7:18 PM
bryant added a comment.Aug 9 2016, 7:21 PM

Generally lacking test coverage, and could consider using std::begin/std::end rather than member begin/end to make sure these algorithms work with arrays and other things without member begin/end.

I'd be happy to write tests for this, but where would they live, filesystem-wise? I would assume under test/*, but am unable to locate any tests of other STLExtra constructs.

Regarding using this with raw C arrays, I'm not sure that would be possible. From memory, C++11 compilers have special case handling for ranged-fors on raw arrays. You could certainly pass in initializer_list<T> into zip/zip_first, but then the initializer_list proxy would already have begin/end member functions.

mehdi_amini edited edge metadata.Aug 9 2016, 8:35 PM

I'd be happy to write tests for this, but where would they live, filesystem-wise?

unittests/ADT.

bryant updated this revision to Diff 67457.Aug 9 2016, 9:22 PM
bryant edited edge metadata.

Support zipping raw C arrays with std::{begin,end}.

mehdi_amini added inline comments.Aug 9 2016, 9:25 PM
include/llvm/ADT/STLExtras.h
537 ↗(On Diff #67457)

Split into a separate patch for this addition (unless it is related to zip in a way that I missed)

bryant updated this revision to Diff 67461.Aug 9 2016, 10:11 PM

Use detail:: namespace. Move out ranged copy/copy_if.

bryant marked an inline comment as done.Aug 9 2016, 10:11 PM
bryant updated this revision to Diff 67471.Aug 10 2016, 12:18 AM
  • When folding bools, replace std::array/std::all_of with a simple constexpr recursive function.
  • Add basic unit test demonstrating rvalue input, mutability, and raw arrays.
bryant updated this revision to Diff 67472.Aug 10 2016, 12:21 AM

accidentally deleted header.

dblaikie added inline comments.Aug 10 2016, 10:24 AM
include/llvm/ADT/STLExtras.h
301 ↗(On Diff #67472)

This keeps a copy (or move) of all its arguments to allow for the rvalue case in a range-for loop? That would have surprising performance characteristics (implicit whole-container copies) for non-temporary parameters...

I think that gets into some pretty major design questions about the behavior here - and the major design problem/question with range proposals in general.

We might need to have a broader discussion about the design for anything like this - might be worth moving that part of the conversation to llvm-dev as I expect it'll be a bit more involved. But maybe here's OK & we can rope a few people in.

(might want to update the description to remove the mention of copy/copy_if now that they've been moved into a separate patch & make the title more specifically about zip range adapter, etc)

include/llvm/ADT/STLExtras.h
241–243 ↗(On Diff #67472)

Recursive implementations only used in constexpr contexts are fine - but a recursive implementation used in a non-constexpr context may still be implemented recursively by the compiler & is usually best avoided. (this is a problem with constexpr currently - where the ideal implementation for constexpr is not the same as the ideal implementation for non-constexpr contexts)

& this isn't being called in a constexpr context, so I'm not sure of the value of flagging it as constexpr or designing it in a way that would be valid constexpr.

bryant added inline comments.Aug 10 2016, 10:52 AM
include/llvm/ADT/STLExtras.h
301 ↗(On Diff #67472)

if by "non-temporary" you mean lvalue input, then no. the corresponding tuple member would be a reference. if it were a copy, the mutability demo in unit test wouldn't work. please correct me if i've misunderstood your question.

bryant added inline comments.Aug 10 2016, 10:56 AM
include/llvm/ADT/STLExtras.h
241–243 ↗(On Diff #67472)

can you find a case where all_true is codegened into a recursive call?

dblaikie retitled this revision from [ADT] Extra STLExtras to [ADT] Zip range adapter.Aug 10 2016, 11:17 AM
dblaikie updated this object.
dblaikie added a reviewer: rsmith.
dblaikie added a subscriber: chandlerc.
dblaikie added inline comments.
include/llvm/ADT/STLExtras.h
241–243 ↗(On Diff #67472)

Can't say I've tried, no. Fair point, though - just not exactly idiomatic (& admittedly variadic templates are on the fringes since they're not often used so idiom is still certainly evolving). Maybe Richard'll have some opinion here too. (or other people - don't mean to limit the review in any way)

301 ↗(On Diff #67472)

Ah, indeed. You've not misunderstood - thanks for pointing out the test/explaining.

If that's all it takes to solve the temporary/non-temporary issue of range adapters, I'm really happy to hear it. But given my lack of understanding here I'm going to punt to Richard Smith, Chandler Carruth, on the C++ committee & who've been, at least somewhat (more than me, at least) aware of the goings on of range proposals, etc.

Thanks for the patch!

Just a few drive-by comments. :)

include/llvm/ADT/STLExtras.h
241–243 ↗(On Diff #67472)

I think constexpr makes some of the compilers we support unhappy; please use LLVM_CONSTEXPR instead.

(Also, FWIW,

template <typename... Bs> bool all_true(Bs... bools) {
  return all_of({bool(bools)...}, identity<bool>{});
}

would eliminate the potential recursion. Looks like this zip magic is declared above llvm::all_of, though.)

245 ↗(On Diff #67472)

Is there a reason we can't just use std::index_sequence/std::make_index_sequence?

317 ↗(On Diff #67472)

Please use /// for function/class documentation.

325 ↗(On Diff #67472)

and here

unittests/Support/IteratorTest.cpp
101 ↗(On Diff #67472)

Can we have one or more tests for zip_first, please? :)

bryant added inline comments.Aug 10 2016, 1:17 PM
include/llvm/ADT/STLExtras.h
241–243 ↗(On Diff #67472)

this is good. i'm going to steal this, if you don't mind.

245 ↗(On Diff #67472)

according to http://en.cppreference.com/w/cpp/utility/integer_sequence it's c++14, whereas i'm aiming for c++11.

bryant updated this revision to Diff 67600.Aug 10 2016, 1:58 PM
  • factor out mutability tests; test zip_first
  • use triple slashes for fn doc comments
  • replace potentially recursive fn with llvm::all_of
bryant marked 3 inline comments as done.Aug 10 2016, 1:59 PM

icmp echo request.

What is the status of this? I ended up writing my own zip implementation (see D25109) before it was pointed out to me that this already exists, but I see there has been no activity in some time.

It looks like this is waiting for comments from chandlerc@ and rsmith@?

include/llvm/ADT/STLExtras.h
251 ↗(On Diff #67600)

For STL-like classes and functions, I believe we prefer to follow STL naming conventions. So I would imagine this should be zip_first

245 ↗(On Diff #67472)

yes but we have llvm::integer_sequence in this very file. Can we use that instead?

bryant updated this revision to Diff 73199.Oct 1 2016, 8:48 AM

Use already-present index_sequence/_of instead of NatList.

bryant marked an inline comment as done.Oct 1 2016, 8:50 AM
bryant added inline comments.
include/llvm/ADT/STLExtras.h
251 ↗(On Diff #67600)

are you sure about this? Zippy/ZipFirst are auxiliary classes that aren't publicly accessible.

245 ↗(On Diff #67472)

you're right, not sure how i missed this. fixed.

bryant marked an inline comment as done.Oct 7 2016, 9:50 AM

ping?

mehdi_amini accepted this revision.Oct 10 2016, 10:14 AM
mehdi_amini edited edge metadata.

LGTM.

This revision is now accepted and ready to land.Oct 10 2016, 10:14 AM
bryant updated this revision to Diff 74278.Oct 11 2016, 11:30 AM
bryant edited edge metadata.

Increase lines of code by 12 with apply_tuple, as suggested by zturner.

If it increases code we shouldn't do it, I thought it would reduce lines of code because I thought I remembered that you had rolled something similar to apply on your own. Sorry for the bad suggestion :-/

zturner accepted this revision.Oct 11 2016, 4:13 PM
zturner added a reviewer: zturner.

Looks fine here too. Feel free to remove the apply() if you think it makes the code shorter or better.

The two main problems are that:

  1. apply_tuple is defined at the bottom of the file which necessitates some very large forward decls.
  2. I don't know of a direct way to invoke apply on a ctor without a wrapper func.

If the entire patch were moved to the bottom, then the clunky decls could be left out. However, zip would be separated from the rest of the iterator adapter definitions. Do you think this is a worthwhile adjustment?

bryant updated this revision to Diff 74349.Oct 12 2016, 2:57 AM
bryant edited edge metadata.
  • revert from using apply_tuple.
  • follow stdlib naming conventions for the support classes in detail.
bryant marked 2 inline comments as done.Oct 12 2016, 2:57 AM
This revision was automatically updated to reflect the committed changes.