Add indirectly_comparable concept
Details
- Reviewers
• Quuxplusone Mordante - Group Reviewers
Restricted Project - Commits
- rG6d722801d1a2: [libc++][ranges] Add indirectly_comparable concept
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
🎄😄
libcxx/include/__iterator/iter_swap.h | ||
---|---|---|
102–103 ↗ | (On Diff #396156) | This code looks fine, but why on earth is it in iter_swap.h? Somewhat tangential query: Is this the last of the <iterator> concepts? or are we still missing some? |
libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp | ||
19–20 | Direct inclusion of <__iterator/readable_traits.h> will fail the modules build. struct Deref { int operator()(int*) const; }; static_assert(!std::indirectly_comparable<int, int, std::less<int>>); // not dereferenceable static_assert(!std::indirectly_comparable<int*, int*, int>); // not a predicate static_assert( std::indirectly_comparable<int*, int*, std::less<int>>); static_assert(!std::indirectly_comparable<int**, int*, std::less<int>>); static_assert( std::indirectly_comparable<int**, int*, std::less<int>, Deref>); static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, Deref, Deref>); static_assert(!std::indirectly_comparable<int**, int*, std::less<int>, std::identity, Deref>); static_assert( std::indirectly_comparable<int*, int**, std::less<int>, std::identity, Deref>); And then a subsumption test in each direction: template<class F> requires std::indirectly_comparable<int*, char*, F> && true constexpr bool subsumes(F f) { return true; } template<class F> requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>> void subsumes(F f); template<class F> requires std::indirect_binary_predicate<F, std::projected<int*, std::identity>, std::projected<char*, std::identity>> && true constexpr bool is_subsumed(F f) { return true; } template<class F> requires std::indirectly_comparable<int*, char*, F> void is_subsumed(F f); static_assert(subsumes(std::less<int>())); static_assert(is_subsumed(std::less<int>())); |
libcxx/include/__iterator/iter_swap.h | ||
---|---|---|
102–103 ↗ | (On Diff #396156) | There are at least permutable, mergable and sortable missing, probably more. |
libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp | ||
19–20 | Why does it make a difference if there is the && true at the end? Is there some "this has more requirements, so it must be stricter"? |
libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp | ||
---|---|---|
19–20 | Yep. See circa 20m–35m in my "Concepts As She Is Spoke" (CppCon 2018). The idea here is that subsumes #2 is constrained by a bunch of stuff, and then subsumes #1 is constrained by all that same stuff plus one additional atomic constraint of "true (line 1, column 73)." So subsumes #1 is strictly more constrained. Note that Concepts does not treat the keywords true and false as magic. FWIW, I find the linebreak positions on lines 30–31 and 39–40 to be weird. Doesn't really matter, though. |
LGTM modulo some nits. Make sure it passes the CI before committing. (I know the CI isn't working at the moment.)
libcxx/docs/Status/RangesPaper.csv | ||
---|---|---|
66 | Maybe update the name ;-) | |
libcxx/include/module.modulemap | ||
597 | I don't see the generated test for this header. | |
libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp | ||
22 | Is there a reason not to include static_assert(!std::indirectly_comparable<int, int, std::less<int>>); // not dereferenceable? | |
32 | I think this can use comment, it looks like magic. (And yes I read the reason for it above.) |
libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp | ||
---|---|---|
22 | +1, also the one before it: static_assert(!std::indirectly_comparable<int, int, std::less<int>>); // not dereferenceable static_assert(!std::indirectly_comparable<int*, int*, int>); // not a predicate FYI I'm not married to those specific code comments. I put them because I thought otherwise it was a little subtle (particularly because these are the first couple of lines, where the reader is still getting a handle on what we're doing here). After the first two lines, the "not a..." explanations get really complicated to explain, plus the reader should have gained a little experience decoding the earlier lines, so I figured comments were more pain than gain at that point. |
- Updated name
- Added line-break
- Removed headers
- Added header test
- Added missing assertions
- Added comment
libcxx/test/std/iterators/iterator.requirements/indirectcallable/indirectinvocable/indirectly_comparable.compile.pass.cpp | ||
---|---|---|
22 | The reason is that they are not in the godbolt link and I copied the code from there :). |
Why is the CI failing? I ran all the generator scripts, but it didn't change anything.
https://buildkite.com/llvm-project/libcxx-ci/builds/7566#fbd04c3f-dcc1-45dd-993c-a9fd09735bdf says:
+ grep -rn '[^ -~]' libcxx/include/ libcxx/include/iterator:145: concept indirectly_comparable = libcxx/include/iterator:146: indirect_binary_predicate<R, projected<I1, P1>, projected<I2, P2>>; // since C++20
This means there's some non-ASCII character in there (on each of those lines). If you copied from eel.is, it's probably a zero-width space character in the vicinity of one of the underscores. A sufficiently dumb text editor will be able to show you exactly where.
Maybe update the name ;-)