使用运行时参数桥接模板 我正在处理一个第三方C++库,它广泛地使用了模板。这使得它很难创建一个C API来从我的框架中使用它

使用运行时参数桥接模板 我正在处理一个第三方C++库,它广泛地使用了模板。这使得它很难创建一个C API来从我的框架中使用它,c++,c,c++11,templates,c-preprocessor,C++,C,C++11,Templates,C Preprocessor,抽象问题,假设库提供以下功能: template <int i> void foo(); template <int i> void zoo(int v); 一个明显的实施可以是: void c_foo(int i) { switch(i) { case 1: foo<1>(); break; case 2: foo<2>(); break; case 3: foo<3>

抽象问题,假设库提供以下功能:

template <int i> void foo();
template <int i> void zoo(int v);
一个明显的实施可以是:

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 c_foo(inti)
{
开关(一){
案例1:foo();break;
案例2:foo();break;
案例3:foo();break;
默认:中断;
};
};
void zoo(int)
也执行同样的操作

如果
i
的可能值的范围很小,则此选项可以正常工作。如果我想处理[1100]中
I
的所有可能值,那么以这种方式编写代码会变得非常难看,因为有很多重复


有没有更简洁的方法来做到这一点,即写更少的代码行?也许使用递归预处理器宏?

您可以在内部使用模板生成必要的代码

一种方法是生成一个包含100个函数指针的调度表,然后在运行时为其编制索引
c_foo
将生成索引的编译时序列并调用助手:

extern "C" void c_foo(int i) {    
    c_foo_impl(std::make_integer_sequence<int,100>{}, i);
}
如果您发现在一些地方需要这个,您可以提取出一些细节,或者使用一个库,例如,它提供了一个
switch\u表
,来执行这种映射


我想问题是这个模板编号是什么?它是类似于内部缓冲区大小,还是更类似于命令字节? 一个假定平均C++程序只生成一些参数值。 也许bast方法将枚举一些典型的缓冲区大小或命令名,并仅实例化它们,因此如果c代码使用您的enum作为参数,它将工作,否则它(严重失败)断言

如果新条目被证明是正确的,那么添加它们将是一件麻烦事,但是您可以为此编写一个脚本


另一种方法可能是生成损坏的命名存根,即生成一个foo\uuu 1()foo\uu 2()等,可能使用boost扩展预处理器来帮助。同样,C程序员会被自动限制在编译时发布的方法和范围内

“也许使用递归预处理器宏?”有许多库提供了帮助宏来实现这一点。例如boost预处理器库。我喜欢这个想法,但我想知道是否每次调用都会重新生成调度表。我想我会尝试一个小小的变化,将指针向量嵌入到结构中,这样我就可以创建该结构的全局实例并使用它进行调度。您可以进行
dispatch
constexpr
以避免重新生成。VS2015生成的汇编程序显示,即使使用
constexpr
,数组也会在每次调用时重新初始化。使用
static
解决问题。刚刚在此处发布了一个相关问题:
extern "C" void c_foo(int i) {    
    c_foo_impl(std::make_integer_sequence<int,100>{}, i);
}
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]();
}
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);
}