使用运行时参数桥接模板 [英] bridging templates with runtime arguments
问题描述
我正在处理一个广泛使用模板的第三方C ++库。
I am dealing with a 3rd party C++ library which makes extensive use of templates. That makes it difficult to create a C API for it to use it from my framework.
抽象这个问题,假设该库提供了以下功能:
Abstracting the problem, suppose the library offers the function:
template <int i> void foo();
template <int i> void zoo(int v);
我想创建一个带有函数头的C API:
I want to create a C API with the function head:
extern "C" void c_foo(int i);
extern "C" void c_zoo(int i, int v);
一个明显的实现可能是:
An obvious implementation could be:
void c_foo(int i)
{
switch(i) {
case 1: foo<1>(); break;
case 2: foo<2>(); break;
case 3: foo<3>(); break;
default: break;
};
};
,对于 void zoo(int)$ c也应这样做$ c>。
如果 i
的可能值范围很小,则此方法很好。如果我想处理[1,100]中 i
的所有可能值,则由于存在大量重复,因此以这种方式编写代码变得非常难看。
This works fine if the range of possible values for i
is small. If I want to handle all possible values of i
in [1,100], then it becomes exceedingly ugly to write code in this way, as there is lot of repetition.
有没有更紧凑的方法来做到这一点,即编写更少的代码行?也许使用递归预处理器宏?
Is there any more compact way to do that, i.e. writing less lines of codes? Perhaps using recursive preprocessor macros?
推荐答案
您可以在内部使用模板来生成必要的代码。
You could use templates internally to generate the necessary code.
一种执行此操作的方法是生成包含100个函数指针的调度表,然后在运行时对其进行索引。 c_foo
将生成索引的编译时序列并调用一个助手:
One way to do this is generate a dispatch table of 100 function pointers, then index it at runtime. c_foo
will generate a compile-time sequence of indices and call a helper:
extern "C" void c_foo(int i) {
c_foo_impl(std::make_integer_sequence<int,100>{}, i);
}
此助手将生成调度表并执行呼叫:
This helper will generate the dispatch table and carry out the call:
template <int... Is>
void c_foo_impl (std::integer_sequence<int,Is...>, int i) {
constexpr std::array<void(*)(), sizeof...(Is)> dispatch = { &foo<Is>... };
//assert or some other error handling for i > sizeof...(Is)
dispatch[i]();
}
然后,您可以为 zoo做同样的事情
:
extern "C" void c_zoo(int i, int v) {
c_zoo_impl(std::make_integer_sequence<int,100>{}, i, v);
}
template <int... Is>
void c_zoo_impl (std::integer_sequence<int,Is...>, int i, int v) {
constexpr std::array<void(*)(int), sizeof...(Is)> dispatch = { &zoo<Is>... };
//assert or some other error handling for i > sizeof...(Is)
dispatch[i](v);
}
如果您发现需要在几个地方使用它,可以抽象出一些细节,或使用诸如 Petra 之类的库,该库提供了 switch_table
来执行这种映射。
If you find that you need this in a few places, you could abstract out some of the details, or use a library such as Petra, which provides a switch_table
to carry out this kind of mapping.
这篇关于使用运行时参数桥接模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!