5
\$\begingroup\$

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?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Aug 13, 2019 at 21:12
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

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.

answered Aug 13, 2019 at 23:11
\$\endgroup\$
1

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.