用于各种类型指针的C ++容器

时间:2016-12-12 02:21:41

标签: c++ containers

我正在尝试为指向不同数据类型的指针创建一个特殊容器。 我们假设我们有结构:

struct data
{
    int *v1;
    double *v2;
};

指针数及其类型是固定的,必须在编译时知道。但我需要一些不同的东西。我有一个可能字段的大型列表(类型+名称)。每个字段可以存在或不存在。我可以使用LARGE struct和所有可能的字段,但我想节省内存。如果字段不存在,我不希望它在容器中占用内存。仍然可以通过名称或唯一代码访问所有当前字段,无需需要强制转换或记住确切类型。
真正的问题在这里结束。还有我自己的想法,你不必阅读,这可能会让你感到困惑。

好的,这就是我现在所拥有的:

class Cont
{
public:
    Cont() {}

    void map(std::string name, void *p)
    {
        m[name] = p;
    }

    template <typename T>
    T *find(std::string name)
    {
        return reinterpret_cast<T *>(m[name]);
    }

private:
    std::map<std::string, void *> m;
};

void handler()
{
    int v1 = 100;
    double v2 = 0.1;

    Cont c;

    c.map("v1", &v1);
    c.map("v2", &v2);

    printf("%d\n", *c.find<int>("v1"));
    printf("%f\n", *c.find<double>("v2"));

}

它的作用和做我需要的。但我正在寻找:
1)更优雅和正确的方式(可能);
2)调用find()时避免指定指针类型的方法。我们在编译时不知道是否存在名为“v1”的值。但我们知道“v1”总是“int”类型。目前我只能看到的解决方案是使用以下宏:

#define V1 *c.find<int>("v1")

然后

printf("%d\n", V1);

此处的字符串“v1”可以替换为唯一代码,以便更快地搜索 因此,主要目标是一次性指定所有可能字段的类型。还有其他想法吗?谢谢! 注意:我知道在许多情况下我的示例会崩溃。为简单起见,我删除了重要的检查。

2 个答案:

答案 0 :(得分:1)

如果您的编译器支持C ++ 17,您可以使用std::variantstd::any作为地图的值;并且您的find()将使用get()(在变体&#39;}中)或std::any_cast来检索该值。

答案 1 :(得分:0)

似乎我达到了目标!方法需要额外的测试,但现在看起来不错。

template <typename T>
class Field
{
public:
    Field(uint32_t _code) : code(_code) {}
    uint32_t code;
};

class Cont
{
public:

    template <typename T>
    void set(Field<T> field, void *p)
    {
        m[field.code] = p;
    }

    template <typename T>
    T *get(Field<T> field)
    {
        return reinterpret_cast<T *>(m[field.code]);
    }

private:
    std::map<uint32_t, void *> m;
};

// All possible fields
const Field   <int>       value1      (0x00000001);
const Field   <double>    value2      (0x00000002);

int main(int argc, char *argv[])
{
    Cont c;

    int temp1 = 400;
    double temp2 = 0.4;

    c.set(value1, &temp1);
    c.set(value2, &temp2);

    printf("%d\n", *c.get(value1));
    printf("%f\n", *c.get(value2));

    return 0;
}

使用名为“Field”的类可以保存字段类型和唯一代码。然后将它传递给get()和set()方法。