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?

\$\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.

\$\endgroup\$
1

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.