[libcxx-commits] [PATCH] D129859: [libc++] Implement ranges::{prev, next}_permutation
Konstantin Varlamov via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jul 19 10:42:34 PDT 2022
var-const requested changes to this revision.
var-const added inline comments.
This revision now requires changes to proceed.
================
Comment at: libcxx/include/CMakeLists.txt:123
__algorithm/ranges_push_heap.h
+ __algorithm/ranges_prev_permutation.h
__algorithm/ranges_remove.h
----------------
Looks like this line is unsorted (might be what the CI is complaining about).
================
Comment at: libcxx/include/__algorithm/ranges_prev_permutation.h:45
+ return {std::move(__last), false};
+ while (true) {
+ auto __ip1 = __i;
----------------
Nit: can you add a blank line before this line?
================
Comment at: libcxx/include/__algorithm/ranges_prev_permutation.h:48
+ --__i;
+ if (std::invoke(__comp, std::invoke(__proj, *__ip1), std::invoke(__proj, *__i))) {
+ auto __j = __last;
----------------
Nit: blank line above.
================
Comment at: libcxx/include/__algorithm/ranges_prev_permutation.h:53
+ } while (!std::invoke(__comp, std::invoke(__proj, *__j), std::invoke(__proj, *__i)));
+ ranges::iter_swap(__i, __j);
+ ranges::reverse(__ip1, __last);
----------------
Nit: blank line above.
================
Comment at: libcxx/include/__algorithm/ranges_prev_permutation.h:57
+ }
+ if (__i == __first) {
+ ranges::reverse(__first, __last);
----------------
Nit: blank line above.
================
Comment at: libcxx/include/__algorithm/ranges_prev_permutation.h:71
+ operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
+ return ranges::__prev_permutation_impl(__first, __last, __comp, __proj);
+ }
----------------
Nit: move?
================
Comment at: libcxx/include/__algorithm/ranges_prev_permutation.h:40-62
+__prev_permutation_impl(_Iter __first, _Sent __sent, _Comp& __comp, _Proj& __proj) {
+ auto __last = ranges::next(__first, __sent);
+ auto __i = __last;
+ if (__first == __last || __first == --__i)
+ return {__last, false};
+ while (true) {
+ auto __ip1 = __i;
----------------
philnik wrote:
> huixie90 wrote:
> > I think this algorithm is complex enough to reuse the classic one. what do you think?
> I think it's harder to combine the two than to use separate ones. The algorithms isn't //that// long, and I would have to teach `reverse` to dispatch between versions. If that changes we can still think about combining the two.
I'd also prefer reuse, but don't want to block this patch on this.
================
Comment at: libcxx/include/algorithm:736
+ requires sortable<I, Comp, Proj>
+ constexpr ranges::prev_permutation_result<I>
+ ranges::prev_permutation(I first, S last, Comp comp = {}, Proj proj = {}); // since C++20
----------------
Please also add the definition of the result types to the synopsis.
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.permutation.generators/ranges.next_permutation.pass.cpp:121
+ test_prev_permutations(iterator_overload);
+ static_assert(test_prev_permutations(iterator_overload));
+ test_prev_permutations(range_overload);
----------------
Question: why is `static_assert` here instead of the common pattern of asserting `test()` in `main()`?
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.permutation.generators/ranges.next_permutation.pass.cpp:45
+template <class Range>
+concept HasNextPermutationR = requires(Range range) { std::ranges::next_permutation(range); };
+
----------------
Does the argument have to be forwarded, perhaps? (here and in the other concept above)
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.permutation.generators/ranges.next_permutation.pass.cpp:63
+void test_permutations() {
+ auto test_prev_permutations = [](auto call_prev_permutation) {
+ auto input = std::array{1, 2, 3, 4, 5, 6};
----------------
There's a bunch of references to `prev_permutation` here. I presume this is simply a copy-pasting issue? (if there's a reason to test them here, please point it out)
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.permutation.generators/ranges.next_permutation.pass.cpp:140
+
+int main(int, char**) { test(); }
----------------
`return 0;` (unless something changed recently in that regard)
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.permutation.generators/ranges.prev_permutation.pass.cpp:91
+
+ auto iterator_overload = [](auto&& first, auto&& last) { return std::ranges::prev_permutation(first, last); };
+ auto range_overload = [](auto&& first, auto&& last) {
----------------
Is the output of `prev_permutation` deterministic? If yes, I'd prefer several simple test cases that check the exact output.
================
Comment at: libcxx/test/support/test_iterators.h:755
+ int* counter_;
+ SwapCountingIterator() = default;
+ constexpr SwapCountingIterator(const Iter& iter, int* counter) : iter_(iter), counter_(counter) {}
----------------
Nit: this creates an object with uninitialized variables (`counter_` and potentially `iter_`), maybe value-initialize those?
================
Comment at: libcxx/test/support/test_iterators.h:758
+
+ constexpr friend void iter_swap(const SwapCountingIterator& lhs, const SwapCountingIterator& rhs) {
+ std::ranges::iter_swap(lhs.iter_, rhs.iter_);
----------------
Would it be possible to just inherit from `Iter` and add the constructor and the `iter_swap` specialization in the derived class?
================
Comment at: libcxx/test/support/test_iterators.h:763
+
+ constexpr SwapCountingIterator& operator++() {
+ ++iter_;
----------------
(I wish we had something like `Boost.Iterator` to cut down on this boilerplate. Of course, it's not related to this patch)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D129859/new/
https://reviews.llvm.org/D129859
More information about the libcxx-commits
mailing list