Discussion:
[std-proposals] Arbitrary function for parameter pack expansion by adding an "std::parameter_map_reduce" function
Jules Pénuchot
2018-10-15 02:33:49 UTC
Permalink
Hello everyone,

I would like to propose an extension for parameter pack expansion.

Currently only infix operators are allowed to reduce parameter pack
expansions. The only ways to replace these operators by an arbitrary
function would be to override them directly, which is obviously not a good
option, or to create a specific decorator class to be able to replace the
operator.

I will use a function piping function as an example case to illustrate the
existing (limited) methods and the one I propose.

Direct override method :
#include <iostream>

template<typename F, typename G>
auto operator | (F f, G g)
{
return [=] (auto e)
{
return g(f(e));
};
};

int main()
{
auto plus_1 = [](auto arg) { return arg + 1; };
auto mult_2 = [](auto arg) { return arg * 2; };

auto pipe = [](auto... Functions)
{
return ( Functions | ... );
};

auto test = pipe(mult_2, mult_2, plus_1, plus_1);

std::cout << test(10) << std::endl;

return 0;
}


Decorator class method :
#include <iostream>

template<typename F>
struct pipe_decorator
{
F f;
};

template<typename Fa, typename Fb>
auto operator | (pipe_decorator<Fa> da, pipe_decorator<Fb> db)
{
auto fun = [=](auto elmt){ return db.f(da.f(elmt)); };

return pipe_decorator<decltype(fun)>{ fun };
}

int main()
{
auto plus_1 = [](auto arg){ return arg + 1; };
auto mult_2 = [](auto arg){ return arg * 2; };

auto pipe = [](auto... Functions)
{
return ( pipe_decorator<decltype(Functions)>{ Functions } | ... ).f;
};

auto test = pipe(mult_2, mult_2, plus_1, plus_1);

std::cout << test(10) << std::endl;

return 0;
}


The decorator method is much better as it avoids overriding the operator
for all the functions, however it is not yet self-contained as it still
requires to create a class and an operator both external to the function we
need it in.

Being able to reduce packs with an arbitrary function would even allow us
to use lambda-capture in this context, which isn't possible in this case
without using std::function and therefore missing the optimizations that
these solutions benefit from; the code is properly unrolled and partially
evaluated at compile-time by gcc 7.1 in both cases. clang 7.0.0 wasn't able
to compile the *direct override method* but it performed the same
optimizations as gcc for the *decorator class method*.

The parameter pack expansion is as simple as a map-reduce, we can easily
alter the function mapped to each parameter but not the reduction function,
and there is no reason other than syntax for such a constraint.

Here's what it could look like :

#include <iostream>

int main()
{
auto plus_1 = [](auto arg){ return arg + 1; };
auto mult_2 = [](auto arg){ return arg * 2; };

auto pipe_funs = [](auto F, auto G)
{
return [=](auto elmt) { return G(F(elmt)); };
};

auto fallthrough = [](auto e)
{
return e;
};

auto pipe = [](auto... Functions)
{
return std::parameter_map_reduce(fallthrough, pipe_funs, Functions...);
};

auto test = pipe(mult_2, mult_2, plus_1, plus_1);

std::cout << test(10) << std::endl;

return 0;
}


The simple addition of such an "std::parameter_map_reduce" function would
make it possible without even changing the language's syntax. The first
argument would be the function to map, the second one would be the reductor
then the rest would be the parameters to reduce. An even more minimalistic
approach would be to add an "std::parameter_reduce" function as we can
already map a function to the parameters, but adding both would expose more
granular options.

Any feedback or criticism regarding this proposal is welcome.

Regards,
Jules Pénuchot
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8788ce93-157b-464a-8325-bfbe296c38b8%40isocpp.org.
Loading...