c++ - 在接口(interface)映射遗留 C 接口(interface)中使用模板参数化类型

标签 c++ templates

我有一个(遗留的)c 界面看起来像这样:

// c interface
#include <stdint.h>
#include <string.h>

typedef enum {
    type_1 = 0, /* native type: uint8_t */
    type_2 = 1, /* native type: double */
    // ... lots of more types defined ...
} thing_type_t;

void thing_set(thing_type_t type, size_t type_size, void* value);
void thing_get(thing_type_t type, size_t type_size, void* return_value);

void thing_set_type_1(uint8_t value);
void thing_get_type_1(uint8_t *value);

void thing_set_type_2(double value);
void thing_get_type_2(double *value);

// ...

所以基本上您可以设置thing,并且根据您选择的thing_type_t 有相应的 native 类型。这个界面我不能改变。

现在我想利用类型多态性做一个 C++ 接口(interface),所以我从客户端可以做类似的事情:

// C++ client
#include <cstdint>

int main(void)
{
    Thing thing;
    thing.set(std::uint8_t(42));
    thing.set(42.0);

    auto uivalue = thing.get<std::uint8_t>();
    auto dvalue = thing.get<double>();

    return 0;
}

它不必完全像这样,但想法是客户端不必担心内部 thing_type_t 类型,而只需使用相应的 native 类型。

我想到的是使用这样的模板:

// C++ interface
#include <cstdint>

class Thing
{
public:
    template <typename T> void set(T value);
    template <typename T> T get();
};

template <> void Thing::set(uint8_t value)
{
    thing_set(type_1, sizeof value, reinterpret_cast<void*>(&value));
}
template <> std::uint8_t Thing::get()
{
    uint8_t ret = 0;
    thing_get(type_1, sizeof ret, &ret);
    return ret;
}

template <> void Thing::set(double value)
{
    thing_set(type_2, sizeof value, reinterpret_cast<void*>(&value));
}
template <> double Thing::get()
{
    double ret = 0;
    thing_get(type_2, sizeof ret, &ret);
    return ret;
}

即我正在为每个 thing_type_t 进行类型专门化,这导致代码臃肿,包含大量重复代码。

我该如何简化它,以便表达 thing_type_t 和 native 类型之间的映射,而无需一次又一次地复制 get/set 函数?

我觉得我应该能够以某种方式使用 thing_type_t 和 native 类型以及映射来参数化 get 和 set 函数。但我不知道该怎么做。

Online editable example

最佳答案

由于实现之间唯一发生变化的是第一个参数,因此我只专门研究该部分:

class Thing
{
public:
    template <typename T> void set(T value)
    {
        thing_set(getType<T>(value), sizeof value, reinterpret_cast<void*>(&value));
    }
    template <typename T> T get()
    {
        T ret = 0;
        thing_get(getType<T>(ret), sizeof ret, &ret);
        return ret;
    }

private:
    template <typename T> thing_type_t getType(T);
};

template <> thing_type_t Thing::getType(uint8_t)
{
    return type_1;
}
template <> thing_type_t Thing::getType(double)
{
    return type_2;
}

关于c++ - 在接口(interface)映射遗留 C 接口(interface)中使用模板参数化类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51820391/

相关文章:

c++ - 模板化类中参数包的语法

c++ - 如何使用 typeid 来计算指针中数据的类型?

c++ - 变体类型和可变参数模板的转换和输出运算符

c++ - 是否可以使用 Google Mock (gmock) 捕获参数?

c++ - 在 Visual Studio 2005 中基于命令行作为 GUI 应用程序或控制台应用程序启动的可执行文件

c++ - OS X 上 Eclipse 中的 OpenGL 和 GLUT

c++ - C++中如何将整数转换为字符串

c++模板类 - 方法中的类变量不可用

c++ - 模板继承层次结构中的循环依赖

c++ - 为什么这个模板不能编译?