[libcxx-commits] [PATCH] D127194: [libc++] Implement ranges::is_permutation

Konstantin Varlamov via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jun 9 18:58:23 PDT 2022


var-const requested changes to this revision.
var-const added inline comments.
This revision now requires changes to proceed.


================
Comment at: libcxx/docs/Status/RangesAlgorithms.csv:36
 Read-only,clamp,Nikolas Klauser,`D126193 <https://llvm.org/D126193>`_,Under review
-Read-only,is_permutation,Not assigned,n/a,Not started
+Read-only,is_permutation,Nikolas Klauser,` <https://llvm.org/>`_,✅
 Read-only,for_each,Nikolas Klauser,`D124332 <https://llvm.org/D124332>`_,✅
----------------
Missing link.


================
Comment at: libcxx/include/__algorithm/is_permutation.h:99
+  while (__first1 != __last1 && __first2 != __last2) {
+    if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2)))
       break;
----------------
Question: using `__invoke` slightly changes the behavior of the non-ranges version of the algorithm as well, right?


================
Comment at: libcxx/include/__algorithm/is_permutation.h:172
                _ForwardIterator2 __last2) {
-  typedef typename iterator_traits<_ForwardIterator1>::value_type __v1;
-  typedef typename iterator_traits<_ForwardIterator2>::value_type __v2;
+  typedef __iter_value_type<_ForwardIterator1> __v1;
+  typedef __iter_value_type<_ForwardIterator2> __v2;
----------------
Optional: can you use `using` like other similar places that were refactored in this patch?


================
Comment at: libcxx/include/__algorithm/ranges_is_permutation.h:26
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
----------------
Please add the language version/no incomplete ranges guard.


================
Comment at: libcxx/include/__algorithm/ranges_is_permutation.h:44
+                  _Proj2 __proj2 = {}) const {
+    return std::__is_permutation(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2);
+  }
----------------
Nit: please move the iterators (and add the include).


================
Comment at: libcxx/include/__algorithm/ranges_is_permutation.h:54
+  bool operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
+    if constexpr (sized_range<_Range1> && sized_range<_Range2>) {
+      if (ranges::distance(__range1) != ranges::distance(__range2))
----------------
Can we do the same optimization in the iterator version (by checking `sized_sentinel_for`)?


================
Comment at: libcxx/include/__algorithm/ranges_is_permutation.h:59
+
+    return std::__is_permutation(ranges::begin(__range1), ranges::end(__range1),
+                                 ranges::begin(__range2), ranges::end(__range2),
----------------
Should this go to the `else` branch of the `if constexpr`?


================
Comment at: libcxx/include/algorithm:1121
 #include <__algorithm/ranges_fill.h>
 #include <__algorithm/ranges_fill_n.h>
 #include <__algorithm/ranges_find.h>
----------------
Missing synopsis.


================
Comment at: libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/ranges.is_permutation.pass.cpp:8
+//===----------------------------------------------------------------------===//
+
+#include <algorithm>
----------------
Missing synopsis.


================
Comment at: libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/ranges.is_permutation.pass.cpp:87
+
+  // the first range is empty
+  test<Iter1, Sent1, Iter2, Sent2, 0, 4>({.input1 = {}, .input2 = {4, 3, 2, 1}, .expected = false});
----------------
Please also check with a single-element range.


================
Comment at: libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/ranges.is_permutation.pass.cpp:95
+  test<Iter1, Sent1, Iter2, Sent2, 0, 0>({.input1 = {}, .input2 = {}, .expected = true});
+
+}
----------------
Nit: there's an unnecessary blank line.


================
Comment at: libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/ranges.is_permutation.pass.cpp:109
+
+constexpr bool test() {
+  test_iterators1<forward_iterator<int*>, sentinel_wrapper<forward_iterator<int*>>>();
----------------
Please also add test cases that use a non-default projection or a non-default predicate.


================
Comment at: libcxx/test/std/algorithms/alg.nonmodifying/alg.is_permutation/ranges.is_permutation.pass.cpp:190
+
+  { // check that the complexity requirements are met with identical ranges
+    {
----------------
Should be `ranges of different sizes` or similar. Also, is there a reason that these test cases aren't part of the `test` function?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127194/new/

https://reviews.llvm.org/D127194



More information about the libcxx-commits mailing list