Date: Tue, 17 Nov 2020 08:59:43 -0600

On Tue, Nov 17, 2020 at 4:46 AM Pilar Latiesa via Std-Proposals <

std-proposals_at_[hidden]> wrote:

> Just a question to the C++ experts.

>

> There are some std algorithms that tend to be much more verbose and

> unclear than the plain loop counterpart. For example, compare:

>

> for (std::size_t i = 0; i < v.size(); ++i)

> u[i] = v[i] / std::sqrt(w[i]);

>

> with:

>

> std::transform(v.begin(), v.end(), w.begin(), u.begin(), [](auto a,

> auto b) { return a / std::sqrt(b); });

>

> The introduction of ranges library was a significant improvement:

>

> std::ranges::transform(v, w, u.begin(), std::divides{}, {}, [](auto b)

> { return std::sqrt(b); });

>

> Furthermore, thanks to the current and forthcoming range adaptors,

> we'll be able to use algorithms in pieces of code that weren't

> previously easily expressible with them. For example:

>

> for (std::size_t i = 0; i < v.size(); ++i)

> u[i] = v[i] * y[i] / std::sqrt(w[i]);

>

> might be written:

>

> std::ranges::transform(std::views::zip(v, w, y), u.begin(), [](auto

> &&Proxy) { auto [a, b, c] = Proxy; return a * b / std::sqrt(c); });

>

> The question is: would it be theoretically possible to add overloads

> to the algorithms such that they accept n-ary callables for iterators

> with tuple-like iter_reference_t, where n is

> tuple_size<iter_reference_t>?

>

> I mean:

>

> std::ranges::transform(std::views::zip(v, w, y), u.begin(), [](auto a,

> auto b, auto c) { return a * b / std::sqrt(c); });

>

This sort of thing is sufficiently common that

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html

suggests a named view:

ranges::copy(

zip_transform([](auto a, auto b, auto c){ return a * b / std::sqrt(c);

}, z, w, y),

u.begin());

>

> or also:

>

> map<string, int> m;

>

> auto sum = std::ranges::accumulate(m, 0, {}, [](auto &, auto i) { return

> i; });

>

But generally, you're not looking for a different algorithm. You're looking

for a function adapter. Boost.Hof calls this unpack (

https://www.boost.org/doc/libs/master/libs/hof/doc/html/include/boost/hof/unpack.html

):

auto sum = std::ranges::fold(m, 0, std::plus(), unpack([](auto&&, auto i){

return i; }));

Which you could also use in the previous example:

ranges::copy(

zip(z, w, y) | views::transform(unpack([]auto a, auto b, auto c){

return a * b / std::sqrt(c)),

u.begin());

Barry

>

> though in this case we'd also have:

>

> auto sum = std::ranges::accumulate(m | std::views::values, 0);

>

> Are there cases in which adding such overloads would cause ambiguities?

>

> Pili

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

std-proposals_at_[hidden]> wrote:

> Just a question to the C++ experts.

>

> There are some std algorithms that tend to be much more verbose and

> unclear than the plain loop counterpart. For example, compare:

>

> for (std::size_t i = 0; i < v.size(); ++i)

> u[i] = v[i] / std::sqrt(w[i]);

>

> with:

>

> std::transform(v.begin(), v.end(), w.begin(), u.begin(), [](auto a,

> auto b) { return a / std::sqrt(b); });

>

> The introduction of ranges library was a significant improvement:

>

> std::ranges::transform(v, w, u.begin(), std::divides{}, {}, [](auto b)

> { return std::sqrt(b); });

>

> Furthermore, thanks to the current and forthcoming range adaptors,

> we'll be able to use algorithms in pieces of code that weren't

> previously easily expressible with them. For example:

>

> for (std::size_t i = 0; i < v.size(); ++i)

> u[i] = v[i] * y[i] / std::sqrt(w[i]);

>

> might be written:

>

> std::ranges::transform(std::views::zip(v, w, y), u.begin(), [](auto

> &&Proxy) { auto [a, b, c] = Proxy; return a * b / std::sqrt(c); });

>

> The question is: would it be theoretically possible to add overloads

> to the algorithms such that they accept n-ary callables for iterators

> with tuple-like iter_reference_t, where n is

> tuple_size<iter_reference_t>?

>

> I mean:

>

> std::ranges::transform(std::views::zip(v, w, y), u.begin(), [](auto a,

> auto b, auto c) { return a * b / std::sqrt(c); });

>

This sort of thing is sufficiently common that

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2214r0.html

suggests a named view:

ranges::copy(

zip_transform([](auto a, auto b, auto c){ return a * b / std::sqrt(c);

}, z, w, y),

u.begin());

>

> or also:

>

> map<string, int> m;

>

> auto sum = std::ranges::accumulate(m, 0, {}, [](auto &, auto i) { return

> i; });

>

But generally, you're not looking for a different algorithm. You're looking

for a function adapter. Boost.Hof calls this unpack (

https://www.boost.org/doc/libs/master/libs/hof/doc/html/include/boost/hof/unpack.html

):

auto sum = std::ranges::fold(m, 0, std::plus(), unpack([](auto&&, auto i){

return i; }));

Which you could also use in the previous example:

ranges::copy(

zip(z, w, y) | views::transform(unpack([]auto a, auto b, auto c){

return a * b / std::sqrt(c)),

u.begin());

Barry

>

> though in this case we'd also have:

>

> auto sum = std::ranges::accumulate(m | std::views::values, 0);

>

> Are there cases in which adding such overloads would cause ambiguities?

>

> Pili

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

Received on 2020-11-17 09:00:00