My aim was to create a function which behaves like the operator .
in Haskell.
Here is what I made:
template <typename F>
auto compose(F&& f)
{
return [a = std::move(f)](auto&&... args){
return a(std::move(args)...);
};
}
template <typename F1, typename F2, typename... Fs>
auto compose(F1&& f1, F2&& f2, Fs&&... fs)
{
return compose(
[first = std::move(f1), second = std::move(f2)]
(auto&&... args){
return second(first(std::move(args)...));
},
std::move(fs)...
);
}
Possible usage:
int main()
{
const auto f = compose([](const auto a, const auto b){return a + b;},
[](const auto n){return n * n;},
[](const auto n){return n + 2;});
std::cout << f(3, 2) << std::endl;
// should output 27 ( (3 + 2) * (3 + 2) + 2 )
}
The full source with a few more examples may be found here.
I'm not sure whether to use std::move
or std::forward
. Which one is better? Any other suggestions?
1 Answer 1
You probably do want std::forward
here. You're using forwarding references with your templated && types, which means that they might actually be lvalues which the rest of the program expects to remain valid. std::move
is basicall a promise that says "The owner is done with this object; feel free to plunder it". Obviously that's dangerous if it's false! std::forward
, by contrast, will intelligently say whether something is free to plunder, based on whether it was free for plundering when passed as a parameter in the first place.
One other thing that I would suggest might be helpful is adding some sort of error detection. It would take a bit of work, but stuffing compose
with a few well placed static_assert lines or similar would make a world of difference when trying to get something to build which has a few layers of composition. I'm thinking you could construct something helpful with is_invocable although that would require c++17.
-
1\$\begingroup\$ Thank you! I struggled with static asserts a bit, yet succeeded in implementing them after all. Here are the results: github.com/nestoroprysk/FunctionComposition/commit/… \$\endgroup\$Nestor– Nestor2019年08月14日 19:44:36 +00:00Commented Aug 14, 2019 at 19:44