我正在尝试为指向不同数据类型的指针创建一个特殊容器。 我们假设我们有结构:
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”可以替换为唯一代码,以便更快地搜索 因此,主要目标是一次性指定所有可能字段的类型。还有其他想法吗?谢谢! 注意:我知道在许多情况下我的示例会崩溃。为简单起见,我删除了重要的检查。
答案 0 :(得分:1)
如果您的编译器支持C ++ 17,您可以使用std::variant或std::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()方法。