好了,我有一个用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(float),TAG_DOUBLE(double数据类型)和TAG ,TAG_List(char *),TAG_COMPOUND(struct nbt_list),TAG_BYTE_ARRAY(struct nbt_compound)。

我现在正试图以一种优雅的方式将其映射到C++,但我无法完成...
char getByte();                     // TAG_BYTE
int16_t getShort();                 // TAG_SHORT
int32_t getInt();                   // TAG_INT
int64_t getLong();                  // TAG_LONG
float getFloat();                   // TAG_FLOAT
double getDouble();                 // TAG_DOUBLE
std::string getString();            // TAG_STRING
std::vector<char> getByteArray();   // TAG_BYTE_ARRAY
std::vector<Tag> getCompound();     // TAG_COMPOUND

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

最佳答案

这可以完成工作:

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]
}

关于c++ - 包装此空指针的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3742405/

10-11 17:02