C++ std::apply made usable

So little C++ so much good!

std::apply is used to Invoke a Callable object with a tuple of arguments.

Somehow that statement left me wanting for more. That is one very corralling definition.

std::apply is a typical example of those numerous standard C++ std lib types begging to be made comfortable and usable.  Not just narrowly usable.  I can (you can, we can) see a bit wider scope for std::apply  use cases. Let’s try.

Certainly, one can try and go ahead and just use it. But.  In its raw form, std::apply requires a lot of typing. That code becomes clunky, unreadable and complex.

So, I made one little wrapper that is really simple but makes std::apply usage, much more palatable.

The API

Design principle in here is: you first make specific “applicator” type, from a specific Callable object. Then you use it, wherever you need it.

Thus summator is a proxy to the services of the summa function. summator  now has the methods encapsulating the required interaction of std::apply and the summa function. Thus it delivers simpler and easier to use interface v.s the naked interaction of std::apply and the Callable it is using.

Please find the suma in the Appendix below.

Let us now see before and after use cases. To each example below, I have added std::apply raw usage, on the line below. So that you can compare and decide what works best for you.

Not a big deal. Shorter but just slightly shorter. Ok, how about using tuples, as primary and only argument type to be passed (by design ) to std::apply. Here is the difference.

At least for me, that’s a big difference in ease of usage. And then there are types that my API can do, and std::apply can not do.

Initializer list’s, std::apply simply does not let you use. And what about native arrays? Yes, I can do too. std::apply can not be called with native array as an argument.

I know std::array is rather nice, and I use it too whenever I can, but in real-life code, native arrays no one can avoid. There is a legacy ocean of them native arrays as arguments.  Instead of writing your own transformations from std array to native array, feel free to use my API.

Stunts?

Ok, I do not advise stunts, but only this time.  What about this “funky” situation:

F( a, b,  F(c, d))

Function result used as one of the arguments to the same function. How do we do that:

As long as you understand the purpose of std::apply, I am pretty sure you will find good use for this little utility.  In that case, just use it. Feel free to experiment.[nextpage title=”The Free Code”]The code is rather simple and lovingly short. C++17 or 20. I am not building console apps so first my primitive logging.

C++ is made to be used in systems programming, aka “the server-side” aka “unattended”, thus I do not use console apps. That logging above is not part of std::apply but here it is, for the sampling code to be used. Now “the core of the trick”.

Usage

summator now exhibits few call operator overloads, you can see in the code above.  The argument is first transformed to tuple like std type and then passed to the apply call on the callable object given at construction time. For example in the case of a native array, it is transformed into the std array, which is “tuple like” type.

In my own tradition, I am not adding any type traits mumbo jumbo compile-time checks. If you use as ‘Callable above something that is not, the compiler will simply not let you use it.

Similarly, if you use the fact all return values are constexpr go for it. C++20 certainly opens the door for compile-time computing wider.

I think this utility is amazingly simple and improves the quality and readability of the code using std::apply considerably. Enjoy.

Appendix

The summa` used to explain the API above. The function we will use as the “callable” specimen to which we will “apply” all kinds of arguments. (But of the same type.)

Of course, all the args above have to be of the same type. They are being simply added together. Hence that static_assert in there. That is almost easy to code. I am sure you will manage without my explanation.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.