c++ - 在运行时处理类型删除的数据 - 如何不重新发明轮子?

标签 c++ c++11 reflection runtime compile-time

我正在编写一些代码来获取如下所示的数据:

enum data_type { INT16 = 0, INT32, UINT64, FLOAT, TIMESTAMP };
struct buffer {
    data_type element_type;
    size_t    size; // in elements of element_type, not bytes
    void*     data;
}

(这是简化的;实际上在这个结构中还有很多类型,更多字段等)

现在,我发现自己编写了一堆实用程序代码以在编译时将枚举值“转换”为实际类型,反之亦然。然后我意识到我需要做一些我需要在运行时做同样的事情,并且使用可变数量的缓冲区......所以现在,除了基于类型特征的值和枚举查找之外 -基于模板参数的类型查找 - 我正在编写查找 std::type_info 的代码。有点乱。

但实际上 - 我不应该这样做。它是重复的,我绝对确定我正在重新发明轮子 - 实现已经写过很多次的东西:编译器、DBMS、数据文件解析器、序列化库等等。

我能做些什么来尽量减少我在这项工作上的浪费?

注意事项:

  • 我在运行时获取这些缓冲区,不能只在编译时取消删除类型(例如使用 type_traits)。
  • 我无法更改 API。或者更确切地说,我可以在代码中更改任何我想要的内容,但我仍然会在内存中获取此布局中的数据。
  • 我不只是将这些缓冲区作为输入,我还需要将它们作为输出。
  • 我偶尔需要同时处理许多不同的缓冲区 - 甚至数量可变(例如 foo(buffer* buffers, int num_buffers);
  • C++11 解决方案优于较新的标准版本。
  • 我实际上经常使用 gsl,所以如果您愿意,可以在您的答案中使用它。至于 Boost - 这在政治上可能难以依赖,但我想就 StackOverflow 问题而言,这很好。

最佳答案

这里的目标应该是尽快回到 C++ 类型系统。为此,应该有一个中央函数根据(运行时)data_type 进行切换,然后将每个案例交给一个(编译时)模板版本。

您没有说明相关函数的外观,但这里有一个示例:

template<typename T>
struct TypedBuffer
{
  TypedBuffer(void* data, size_t elementCount) { /* ... */ }
  // ...
};

template<typename T>
void handleBufferTyped(void* data, size_t elementCount)
{
  TypedBuffer<T> buf(data, elementCount);
  // Do whatever you want - you're back in the type system.
}

void handleBuffer(buffer buf)
{
  switch (buf.element_type)
  {
  case INT16:     handleBufferTyped<int16_t>(buf.data, buf.size); break;
  case INT32:     handleBufferTyped<int32_t>(buf.data, buf.size); break;
  case UINT64:    handleBufferTyped<uint64_t>(buf.data, buf.size); break;
  case FLOAT:     handleBufferTyped<float>(buf.data, buf.size); break;
  case TIMESTAMP: handleBufferTyped<std::time_t>(buf.data, buf.size); break;
  }
}

如果需要,您还可以让 TypedBuffer 从非模板基类继承,这样您就可以多态地从 handleBuffer 返回,但这混合了很多范例,可能不必要。

关于c++ - 在运行时处理类型删除的数据 - 如何不重新发明轮子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53080705/

相关文章:

c++ - 如何编写将 C++ 代码作为输入的 C++ 代码生成器?

c++ - 这个右值签名模式有意义吗?

c++ - C++中的原子指针和线程间传递对象

c++ - C++中函数返回的值是右值吗?无法使用复制/move 构造函数初始化实例

c++ - 为模板化 key 专门化 std::hash

Java反射丢失注解信息

reflection - 如何使用反射制作 map 指针?

c++ - 从 C/C++ 到 NASM src

c++ - lambda 采用 `char` 参数

c++ - 用随机值填充通用 vector