首页 > 解决方案 > 模板生成一百个C回调函数,编译不慢

问题描述

我需要将一百个回调函数的顺序传递给 C 库。我所有的回调都将非常相似,除了他们需要知道它注册了哪个“键”。C API 不允许回传上下文。

换句话说,这是 API:

void register_for_event(int event_type, void(*callback)());

我想出了这个模板元编程:

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>(){}

但是有没有办法写这个:

任何版本的 C++,直到 C++20,都适合我。

我试图避免使用宏,尽管对我来说宏在这里有什么帮助并不明显。

我可以使用 shell 脚本的代码生成。如果我找不到更好的 C++ 原生方式,我可能最终会这样做。但我也对其他可能的原生 C++ 方式感兴趣。

标签: c++templatestemplate-meta-programming

解决方案


这是一个 C++17 的答案:

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

它使用 C++17 折叠表达式扩展模板参数包。不确定它在您的场景中是否编译得更快,但在 g++ -O3 下它的速度要快 4 倍。即使在 -Og 下,它也会生成展开代码而不是 100 深度递归。

你可以使用这里的技巧在 C++11/C++14 下做同样的事情。

您可以通过使用立即调用的可变参数模板化 lambda 函数来摆脱额外的函数,但它不会更具可读性;)


推荐阅读