使用运行时参数桥接模板

2024-04-02

我正在处理一个广泛使用模板的第三方 C++ 库。这使得创建 C API 以便从我的框架中使用它变得困难。

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

template <int i> void foo();
template <int i> void zoo(int v);

我想创建一个带有函数头的 C API:

extern "C" void c_foo(int i);
extern "C" void c_zoo(int i, 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 zoo(int).

如果可能值的范围为i是小。如果我想处理所有可能的值i在[1,100]中,那么用这种方式编写代码就变得非常难看,因为有很多重复。

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


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

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

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]();
}

然后你可以做同样的事情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 https://github.com/jacquelinekay/petra,它提供了一个switch_table来进行这种映射。

现场演示 http://coliru.stacked-crooked.com/a/a30814607651e96e

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用运行时参数桥接模板 的相关文章

  • C# SmtpClient编程中如何设置带有中文的附件文件名?

    我的代码如下 ContentType ct new ContentType ct MediaType MediaTypeNames Application Octet ct Name 这是一个很长的中文文件名希望能用它在附件名中 Doc A
  • 是否需要销毁运算符删除的形式才能真正销毁对象?

    C 20 添加了破坏形式operator delete区别于std destroying delete t范围 它导致delete表达式在调用之前不再销毁对象operator delete 目的是在显式调用对象的析构函数和释放内存之前 允许
  • 是否可以使用 http url 作为 DirectShow .Net 中源过滤器的源位置?

    我正在使用 DirectShow Net 库创建一个过滤器图 该过滤器图通过使用 http 地址和 WM Asf Writer 来流式传输视频 然后 在网页上 我可以使用对象元素在 Windows Media Player 对象中呈现视频源
  • C#.Net 邮件将进入垃圾邮件文件夹

    我正在从 ASP net Web 应用程序发送电子邮件 邮件发送成功 没有失败 但大多数都进入了垃圾邮件文件夹 请帮助我克服垃圾邮件过滤器 我的发送邮件代码 public void SendMail string FromAddress s
  • 捕获 .aspx 和 .ascx 页面中的异常

    问题说明了一切 请看以下示例代码 ul li li ul
  • C# 中的 Stack<> 实现

    我最近一直在实现递归目录搜索实现 并且使用堆栈来跟踪路径元素 当我使用 string Join 连接路径元素时 我发现它们被颠倒了 当我调试该方法时 我查看了堆栈 发现堆栈内部数组中的元素本身是相反的 即最近 Push 的元素位于内部数组的
  • 在 C 语言中,为什么数组的地址等于它的值?

    在下面的代码中 指针值和指针地址与预期不同 但数组值和地址则不然 怎么会这样 Output my array 0022FF00 my array 0022FF00 pointer to array 0022FF00 pointer to a
  • strlen() 编译时优化

    前几天我发现你可以找到编译时strlen使用这样的东西 template
  • 在 C++ 代码中转换字符串

    我正在学习 C 并开发一个项目来练习 但现在我想在代码中转换一个变量 字符串 就像这样 用户有一个包含 C 代码的文件 但我希望我的程序读取该文件并插入将其写入代码中 如下所示 include
  • 如何在 C# 中将 Json 转换为对象

    我想将 Json 转换为 C 中的对象 这里的 Json 是 值 e920ce0f e3f5 4c6f 8e3d d2fbc51990e4 如何使用 Object 问题看似愚蠢 但其实并不那么愚蠢 我没有简单的 Json 我有 IEnume
  • 如何修复错误:“检测到无法访问的代码”

    我有以下代码 private string GetAnswer private int CountLeapYears DateTime startDate return count String answer GetAnswer Respo
  • Makefile 和 .Mak 文件 + CodeBlocks 和 VStudio

    我对整个 makefile 概念有点陌生 所以我对此有一些疑问 我正在 Linux 中使用 CodeBlocks 创建一个项目 我使用一个名为 cbp2mak 的工具从 CodeBlocks 项目创建一个 make 文件 如果有人知道更好的
  • JavaScript 错误:MVC2 视图中的条件编译已关闭

    我试图在 MVC2 视图页面中单击时调用 JavaScript 函数 a href Select a JavaScript 函数 function SelectBenefit id code alert id alert code 这里 b
  • OpenGL:如何检查用户是否支持glGenBuffers()?

    我检查了文档 它说 OpenGL 版本必须至少为 1 5 才能制作glGenBuffers 工作 用户使用的是1 5版本但是函数调用会导致崩溃 这是文档中的错误 还是用户的驱动程序问题 我正在用这个glGenBuffers 对于VBO 我如
  • Unity c# 四元数:将 y 轴与 z 轴交换

    我需要旋转一个对象以相对于现实世界进行精确旋转 因此调用Input gyro attitude返回表示设备位置的四元数 另一方面 这迫使我根据这个四元数作为默认旋转来计算每个旋转 将某些对象设置为朝上的简单方法如下 Vector3 up I
  • 如何在多线程应用程序中安全地填充数据并 Refresh() DataGridView?

    我的应用程序有一个 DataGridView 对象和一个 MousePos 类型的列表 MousePos 是一个自定义类 它保存鼠标 X Y 坐标 类型为 Point 和该位置的运行计数 我有一个线程 System Timers Timer
  • 读取依赖步行者输出

    I am having some problems using one of the Dlls in my application and I ran dependency walker on it i am not sure how to
  • 以编程方式创建 Blob 存储容器

    我有一个要求 即在创建公司时 在我的 storageaccount 中创建关联的 blob 存储容器 并将容器名称设置为传入的字符串变量 我已尝试以下操作 public void AddCompanyStorage string subDo
  • C++ 指针引用混淆

    struct leaf int data leaf l leaf r struct leaf p void tree findparent int n int found leaf parent 这是 BST 的一段代码 我想问一下 为什么
  • 如何为有时异步的操作创建和实现接口

    假设我有数百个类 它们使用 计算 方法实现公共接口 一些类将执行异步 例如读取文件 而实现相同接口的其他类将执行同步代码 例如将两个数字相加 为了维护和性能 对此进行编码的好方法是什么 到目前为止我读到的帖子总是建议将异步 等待方法冒泡给调

随机推荐