[libcxx-commits] [PATCH] D119589: [libc++][ranges] Implement ranges::min
Konstantin Varlamov via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Mar 8 17:00:05 PST 2022
var-const added a comment.
@philnik Can you also update `RangesAlgorithms.csv`?
================
Comment at: libcxx/include/__algorithm/ranges_min.h:61
+
+ _LIBCPP_ASSERT(__first != __last, "range has to have at least one element");
+
----------------
Question: the Standard has the requirement that the range is not empty for both this overload and the `initializer_list` overload, but it is only checked here. AFAICT, `__min_element::__fn::__go` doesn't do this check. Is there a reason to only apply this check here?
================
Comment at: libcxx/include/__algorithm/ranges_min.h:66
+ if (std::invoke(__comp, std::invoke(__proj, *__first), std::invoke(__proj, __result)))
+ __result = *__first;
+ }
----------------
Some thoughts: this could lead to a lot of copying in the worst case. `min_element` doesn't have this problem because it stores the iterator instead; however, it's fine for `min_element` operating on `forward_iterator`s but cannot be used here since we're iterating an `input_range`. It probably doesn't matter in most scenarios, but in the worst case, I could imagine that calling `min` on `std::vector<ExpensiveToCopy>` could result in copying every single element if the vector happens to be in descending order.
I wonder if it would be worthwhile to have an `if constexpr` to only copy iterators if the range is a forward range, and fall back to this implementation otherwise?
================
Comment at: libcxx/include/__ranges/take_view.h:121
auto __n = ranges::size(__base_);
- // TODO: use ranges::min here.
- return std::min(__n, static_cast<decltype(__n)>(__count_));
+ return ranges::min(__n, static_cast<decltype(__n)>(__count_));
}
----------------
Thanks for going back to fix this! Sorry about the annoying comment -- do you know if this change affects the visible behavior of `take_view` (e.g., some code compiles now that wouldn't compile previously, or vice versa)? If yes, could you please add a test(s) for this?
================
Comment at: libcxx/include/algorithm:54
+ indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less>
+ constexpr borrowed_iterator_t<R> ranges::min(R&& r, Comp comp = {}, Proj proj = {}); // since C++20
}
----------------
Does the overload taking an `initializer_list` also need to be added?
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.min.pass.cpp:21
+// indirect_strict_weak_order<projected<iterator_t<R>, Proj>> Comp = ranges::less>
+// constexpr borrowed_iterator_t<R> ranges::min(R&& r, Comp comp = {}, Proj proj = {});
+
----------------
The `initializer_list` overload also seems to be missing from here.
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.min.pass.cpp:26
+#include <cassert>
+#include <random>
+#include <ranges>
----------------
Nit: `<random>` seems unused?
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.min.pass.cpp:43
+ int i;
+ bool operator<(const NotTotallyOrdered& o) const && { return i < o.i; }
+};
----------------
Should this be `TotallyOrderedRval`? Also, wouldn't this class need at least an equality operator to be totally ordered?
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.min.pass.cpp:69
+ decltype(auto) ret = std::ranges::min(a[0], a[1], {}, &S::i);
+ ASSERT_SAME_TYPE(decltype(ret), const S&);
+ assert(&ret == &a[1]);
----------------
Nit: it seems like this test uses both `static_assert` and `ASSERT_SAME_TYPE` for comparing types, can it be consistent?
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.min.pass.cpp:122
+ assert(ret == 5);
+ }
+ { // test comparator
----------------
Nit: consider adding newlines between braced scopes. I just think it makes it easier to separate different test cases visually.
================
Comment at: libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.min.pass.cpp:160
+
+int main(int, char**) {
+ test();
----------------
It seems like more SFINAE tests are needed -- I don't think constraints such as `input_range`, `copyable`, `indirectly_copyable_storable`, etc. are currently being checked.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D119589/new/
https://reviews.llvm.org/D119589
More information about the libcxx-commits
mailing list