[libcxx-commits] [PATCH] D122173: [libc++][ranges] Implement ranges::transform
Konstantin Varlamov via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Mar 23 19:39:57 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:47
Write,fill_n,Not assigned,n/a,Not started
-Write,transform,Not assigned,n/a,Not started
+Write,transform,Nikolas Klauser,n/a,✅
Write,generate,Not assigned,n/a,Not started
----------------
Can you add a link to this patch here?
================
Comment at: libcxx/include/__algorithm/ranges_transform.h:44
+
+ template <class _InputIterator, class _Sentinel,
+ class _OutputIterator,
----------------
Mordante wrote:
> Is there a reason why the naming of the types and variables differs from the other ranges algorithms?
> For example `ranges_find.h` uses
> ```
> template <input_iterator _Ip, sentinel_for<_Ip> _Sp, class _Tp, class _Proj = identity>
> requires indirect_binary_predicate<ranges::equal_to, projected<_Ip, _Proj>, const _Tp*>
> _LIBCPP_HIDE_FROM_ABI constexpr
> _Ip operator()(_Ip __first, _Sp __last, const _Tp& __value, _Proj __proj = {}) const {
> auto __pred = [&](auto&& __e) { return std::forward<decltype(__e)>(__e) == __value; };
> return ranges::__find_if_impl(std::move(__first), std::move(__last), __pred, __proj);
> }
>
> ```
> I think it improves our codebase when we keep these names consistent.
> I'm also not to fond of `_InputIterator` and `_OutputIterator`, they are used in the non-range algorithms and there they use the LegacyIterators. So I like that the range based algorithms use a different naming scheme,
FWIW, I'm mildly in favor of using longer names (though I can see the argument for terser names given how verbose the template parameters are in these functions). I think range algorithms (both committed and in flight) aren't currently consistent in this regard.
================
Comment at: libcxx/include/algorithm:104
+ constexpr ranges::unary_transform_result<I, O>
+ transform(I first1, S last1, O result, F op, Proj proj = {}); // since C++20
+ template<input_range R, weakly_incrementable O, copy_constructible F,
----------------
Nit: `s/first1/first/` (same for `last1`).
================
Comment at: libcxx/include/algorithm:110
+ transform(R&& r, O result, F op, Proj proj = {}); // since C++20
+ template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2,
+ weakly_incrementable O, copy_constructible F, class Proj1 = identity,
----------------
Nit: can you add blank lines at least between the unary and binary versions of `transform`, and perhaps between all of them? As it stands, I found it a little hard to find where one functions ends and another one starts due to how verbose the template arguments are.
================
Comment at: libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.pass.cpp:59
+static_assert(!HasTranformR<InputRangeNotSentinelSemiregular>);
+static_assert(!HasTranformR<InputRangeNotSentinelEqualityComparableWith>);
+
----------------
To make the SFINAE test exhaustive, I think it also needs to check the `weakly_incrementable`, `copy_constructible`, `indirectly_writeable`, etc. constraints.
================
Comment at: libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.pass.cpp:78-84
+ int a[] = {1, 2, 3, 4, 5};
+ int b[5];
+ std::same_as<std::ranges::in_out_result<In1, Out>> decltype(auto) ret =
+ std::ranges::transform(In1(a), Sent1(In1(a + 5)), Out(b), [](int i) { return i * 2; });
+ assert((std::to_array(b) == std::array{2, 4, 6, 8, 10}));
+ assert(base(ret.in) == a + 5);
+ assert(base(ret.out) == b + 5);
----------------
Optional: do you think it would be worthwhile to try reducing duplication here? Perhaps something like:
```
template <class In1, class Out>
struct Result {
std::ranges::in_out_result<In1, Out> ret;
Out* out = nullptr;
};
// ...
int a[] = {1, 2, 3, 4, 5};
int b1[5], b2[5];
std::same_as<std::ranges::in_out_result<In1, Out>> decltype(auto) ret_iter =
std::ranges::transform(In1(a), Sent1(In1(a + 5)), Out(b1), [](int i) { return i * 2; });
auto range = std::ranges::subrange(In1(a), Sent1(In1(a + 5)));
std::same_as<std::ranges::in_out_result<In1, Out>> decltype(auto) ret =
std::ranges::transform(range, Out(b2), [](int i) { return i * 2; });
for (const auto& result : {Result{ret_iter, b1}, Result{ret_range, b2}}) {
assert((std::to_array(result.out) == std::array{2, 4, 6, 8, 10}));
assert(base(result.ret.in) == a + 5);
assert(base(result.ret.out) == b + 5);
}
```
================
Comment at: libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.pass.cpp:111
+ }
+ {
+ int a[] = {1, 2, 3, 4, 5};
----------------
Mordante wrote:
> I find this test with the extra whitespace more readable, could you adjust the other test cases in this file accordingly?
+1.
================
Comment at: libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.pass.cpp:181
+
+ { // second range empty (binary)
+ {
----------------
Perhaps also check the case when both ranges are empty for binary?
================
Comment at: libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.pass.cpp:209-212
+ }
+
+
+ { // first range one element
----------------
Nit: one extra blank line.
================
Comment at: libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.pass.cpp:331
+ std::same_as<std::ranges::in_out_result<std::ranges::dangling, int*>> auto ret =
+ std::ranges::transform(std::array{1, 2, 3, 5, 4}, b.data(), [](int i) { return i * i; });
+ assert((b == std::array{1, 4, 9, 25, 16}));
----------------
Nit: I think continued lines should be indented 4 columns.
================
Comment at: libcxx/test/std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.pass.cpp:415
+ test();
+ static_assert(test());
+}
----------------
Please add `return 0`.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D122173/new/
https://reviews.llvm.org/D122173
More information about the libcxx-commits
mailing list