包装这个void指针的最佳方法是什么?

时间:2010-09-18 16:14:51

标签: c++ c polymorphism wrapper

好吧,我在C中编写的库可以读取文件并提供对其数据的访问。数据是打字的,所以我使用了无效指针和一些访问函数:

typedef struct nbt_tag
{
    nbt_type type; /* Type of the value */
    char *name;    /* tag name */

    void *value;   /* value to be casted to the corresponding type */

} nbt_tag;

int64_t *nbt_cast_long(nbt_tag *t)
{
    if (t->type != TAG_LONG) return NULL;

    return (int64_t *)t->value;
}

对于不同类型(内置插件:TAG_BYTE(char),TAG_SHORT(int16_t),TAG_INT(int32_t),TAG_LONG(int64_t),TAG_FLOAT({ {1}}),TAG_DOUBLE(float),TAG_STRING(double)和一些稍微复杂的数据类型,TAG_List(char *),TAG_COMPOUND(struct nbt_list), TAG_BYTE_ARRAY(struct nbt_compound)。

我现在正试图以优雅的方式将其映射到C ++,但我无法完成它......

struct nbt_byte_array

这感觉太冗长了......还有更好的方法吗?

5 个答案:

答案 0 :(得分:3)

这可以完成这项工作:

template <int> struct TypeTag {};
template <> struct TypeTag<TAG_BYTE> { typedef char type; };
// ...
template <> struct TypeTag<TAG_COMPOUND> { typedef vector<Tag> type; };

template <int tag>
typename TypeTag<tag>::type getValue(nbt_tab* t)
{
    if (t->type != tag) ... // throw an exception
    return *reinterpret_cast<typename TypeTag<tag>::type*>(t-value);
}

并像这样使用它:

char x = getValue<TAG_BYTE>(t);
vector<Tag> v = getValue<TAG_COMPOUND>(t);

您可能想要添加

等特色
template <>
vector<Tag> getValue<TAG_COMPOUND>(nbt_tab* t)
{
    if (t->type != TAG_COMPOUND) ... // throw something
    vector<Tag> ans(/* size */); // [rely on named return value optimization]

    // Fill the vector with your data

    return ans; // [Pray for the copy constructor not to get called]
}

答案 1 :(得分:0)

你可以模板化这个功能。

template <typename T>
typename T get();

答案 2 :(得分:0)

不是一个直接的答案,但看看VARIANT(在Windows中),以及相应的CComVariant和_variant_t包装类:这基本上是相同的,你可能能够从如何在那里完成它的一些见解

我做过像模板转换这样的东西,其中复杂性在对象中,但它很容易使用,但是YMMV。

答案 3 :(得分:0)

有一些方法可以使用模板voodoo将其全部减少到get<X>()函数(可能有一些特化)。但是,你可以通过编写那些getX函数的简单性进行权衡,因为这些函数可能需要为模板机制和/或某些模板特化编写类似于小类型特征的基础结构。

如果支持的不同类型的数量永远(或很少)将会发生变化,那么最简单且最容易理解的可能只是那些不同的getX函数。它可能很冗长,但这些函数应该非常快速地编写和调试。

另一方面,如果你对模板感到满意,你当然可以尝试这种方法。

答案 4 :(得分:0)

您可以使用boost :: variant。此类型可以存储它的任何模板参数,并且可以查询它包含的模板参数。只需将一堆它们放在一个向量中,然后返回对您喜欢的变体的引用。