Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template generating a hundred C callback functions, without slow compilation

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:

  • easier to read
  • faster to compile (the above adds several seconds to building the file, with gcc)

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.

like image 377
Thomas Avatar asked Nov 12 '20 16:11

Thomas


Video Answer


1 Answers

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 ;)

like image 91
Botje Avatar answered Oct 21 '22 08:10

Botje