[libcxx-commits] [PATCH] D128983: [libcxx][ranges] implement `std::ranges::set_difference`

Konstantin Varlamov via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jul 2 14:31:11 PDT 2022


var-const requested changes to this revision.
var-const added a comment.
This revision now requires changes to proceed.

Looks pretty good overall, the only substantial comment is about avoid observable changes in behavior in the classic `set_difference` algorithm. Thanks for working on this!



================
Comment at: libcxx/docs/Status/RangesAlgorithms.csv:64
 Merge,merge,Hui Xie,n/a,✅
-Merge,set_difference,Hui Xie,n/a,Not started
+Merge,set_difference,Hui Xie,n/a,✅
 Merge,set_intersection,Hui Xie,n/a,Not started
----------------
Please add a link to this patch.


================
Comment at: libcxx/include/__algorithm/ranges_set_difference.h:46
+      input_iterator _InIter2,
+      std::sentinel_for<_InIter2> _Sent2,
+      weakly_incrementable _OutIter,
----------------
Nit: unnecessary `std::`.


================
Comment at: libcxx/include/__algorithm/ranges_set_difference.h:50
+      class _Proj1 = identity,
+      class _Proj2 = identity >
+    requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2>
----------------
Nit: unnecessary (I think) space. Is this done by `clang-format`? If yes, it's not worth changing.


================
Comment at: libcxx/include/__algorithm/set_difference.h:38
+    class _Proj2>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 pair<typename decay<_InIter1>::type, typename decay<_OutIter>::type>
+__set_difference(
----------------
Does using `decay` here lead to any observable difference?


================
Comment at: libcxx/include/__algorithm/set_difference.h:53
+      ++__result;
+    } else if (std::__invoke(__comp, std::__invoke(__proj2, *__first2), std::__invoke(__proj1, *__first1))) {
+      ++__first2;
----------------
Wouldn't using `invoke` here create an observable change in behavior for the classic algorithm? It seems like it would cause e.g. passing a pointer to member to work with the classic algorithm which wasn't the case before.

Instead, I would strongly recommend the following trick: in the range algorithm, create a lambda that wraps the comparator and the projection functors and pass it as the comparator. It also avoids the need to pass the projections directly. See e.g. `ranges_sort.h`:
```
    auto&& __projected_comp = ranges::__make_projected_comp(__comp, __proj);
    std::__sort_impl(std::move(__first), __last_iter, __projected_comp);
```


================
Comment at: libcxx/include/__algorithm/set_difference.h:78
 template <class _InputIterator1, class _InputIterator2, class _OutputIterator>
-inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
-_OutputIterator
-set_difference(_InputIterator1 __first1, _InputIterator1 __last1,
-               _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result)
-{
-    return _VSTD::set_difference(__first1, __last1, __first2, __last2, __result,
-                                __less<typename iterator_traits<_InputIterator1>::value_type,
-                                       typename iterator_traits<_InputIterator2>::value_type>());
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator set_difference(
+    _InputIterator1 __first1,
----------------
Optional: you can also `s/_LIBCPP_INLINE_VISIBILITY/_LIBCPP_HIDE_FROM_ABI/` since you're changing this line anyway. `_LIBCPP_HIDE_FROM_ABI` is the newer name for the same macro (we use it in new code and IMO it's good to update the old code to use the new name when opportunity arises).


================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/ranges_set_difference.pass.cpp:96
+
+// !mergeable<iterator_t<R1>, iterator_t<R2>, O, Comp, Proj1, Proj2>
+static_assert(!HasSetDifferenceRange< UncheckedRange<MoveOnly*>, UncheckedRange<MoveOnly*>, MoveOnly*>);
----------------
Ultranit: qualify `std::` for consistency?


================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/ranges_set_difference.pass.cpp:149
+
+  // range 2 shorter than range 1
+  {
----------------
Can you also check the case when the lengths are the same (but the elements are different)?


================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/ranges_set_difference.pass.cpp:205
+
+  // check that ranges::dangling is returned for non-borrowed_range and iterator_t is returned for borrowed_range
+  {
----------------
Nit: the test case doesn't seem to check `borrowed_range`, so remove that part of the comment?


================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/ranges_set_difference.pass.cpp:234
+template <class InIter2, class OutIter>
+constexpr void withAllInIter1Iterators() {
+  testImpl<cpp20_input_iterator<int*>, InIter2, OutIter>();
----------------
Nit: probably needs renaming for consistency with the `merge` test.


================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/ranges_set_difference.pass.cpp:244
+constexpr void withAllInIter1InIter2Iterators() {
+  withAllInIter1Iterators<cpp20_input_iterator<int*>, OutIter>();
+  withAllInIter1Iterators<forward_iterator<int*>, OutIter>();
----------------
Question: does `cpp17_input_iterator` not work? If yes, can you add a short comment indicating why it doesn't work, to make it clear it wasn't forgotten but deliberately omitted?


================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.set.operations/set.difference/ranges_set_difference.pass.cpp:261
+  // check that every element is copied exactly once
+  struct TracedCopy {
+    int copy_assign = 0;
----------------
Since this class is already used here and in `merge` test, and will likely be used more in further tests, it should probably be moved into a shared header with helpers.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D128983



More information about the libcxx-commits mailing list