I need to pass order of a hundred callback functions to a C library. All my callbacks will be very similar, except that they need to know which "key" it was registered for. The C API doesn't allow an context to be passed back.
In other words this is the API:
void register_for_event(int event_type, void(*callback)());
I came up with this template metaprogramming:
template<int event_type>
void event_handler() {
std::cout << "Event: " << event_type << std::endl;
}
template <int n = 100>
void register_event_handlers() {
register_for_event(n, event_handler<n>);
register_event_handlers<n-1>();
}
template<> void register_event_handlers<0>(){}
But is there a way to write this:
Any version of C++, up to C++20, would work for me.
I'm trying to avoid macros, though it's not obvious to me how macros would even help here.
I could use code generation from shell script. I may end up doing this if I can't find a better C++-native way. But I'm also interested in what other native C++ ways are possible.
Here is a C++17 answer:
template <std::size_t... I>
void register_via_pack(std::index_sequence<I...>) {
( (register_for_event(I, event_handler<I>)),... );
}
register_via_pack(std::make_index_sequence<100>{});
It expands a template parameter pack using a C++17 fold expression. Not sure if it compiles faster in your scenario, but it is a good 4 times faster here under g++ -O3. Even under -Og it produces unrolled code instead of a 100-deep recursion.
You can use the trick here to do the same under C++11/C++14.
You can get rid of the extra function by using an immediately-invoked variadic templated lambda function, but it will not be more readable ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With