使用运行时参数桥接模板 [英] bridging templates with runtime arguments

查看:71
本文介绍了使用运行时参数桥接模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一个广泛使用模板的第三方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)

如果 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆