C++ 如何在C+中存储变量数据+;

C++ 如何在C+中存储变量数据+;,c++,variant,C++,Variant,我正在创建一个类来存储关于特定数据源的元数据。元数据在树中结构化,非常类似于XML的结构。元数据值可以是整数、十进制或字符串值 我很好奇C++中有没有一种好的方法来存储这样的情况下的变量数据。我希望变体使用标准库,因此我避免使用可用的COM、Ole和SQL变体类型 我当前的解决方案如下所示: enum MetaValueType { MetaChar, MetaString, MetaShort, MetaInt, MetaFloat, MetaD

我正在创建一个类来存储关于特定数据源的元数据。元数据在树中结构化,非常类似于XML的结构。元数据值可以是整数、十进制或字符串值

我很好奇C++中有没有一种好的方法来存储这样的情况下的变量数据。我希望变体使用标准库,因此我避免使用可用的COM、Ole和SQL变体类型

我当前的解决方案如下所示:

enum MetaValueType
{
    MetaChar,
    MetaString,
    MetaShort,
    MetaInt,
    MetaFloat,
    MetaDouble
};

union MetaUnion
{
    char cValue;
    short sValue;
    int iValue;
    float fValue;
    double dValue;
};

class MetaValue
{
...
private:
    MetaValueType ValueType;
    std::string StringValue;
    MetaUnion VariantValue;
};
MetaValue类有各种Get函数来获取当前存储的变量值,但它最终会使每个值查询都成为一大块if/else if语句,以确定我要查找的值

我还探讨了仅将值存储为字符串,并执行转换以获取不同的变量类型,但就我所见,这导致了一系列内部字符串解析和错误处理,这并不美观,打开了一个关于浮点值的精度和数据丢失问题的旧大罐,并且仍然不能消除上面提到的查询if/else if问题

有没有人使用标准库实现或看到了一个更干净的C++变量数据类型?

< > C++ 17,有.</P> 如果你还不能使用它,你可能会想要。(和,C++17之前,)提供了一种类似但不同的多态性建模类型


作为一个额外的指针,您可以查找“.”

您还可以使用更C-ish的解决方案,该解决方案在您的系统上有一个双精度大小的void*加上您正在使用的类型的枚举。它相当干净,但对于那些对系统的原始字节感到完全满意的人来说,它绝对是一个解决方案。

虽然Konrad的答案(使用现有的标准化解决方案)肯定比编写自己的易出错版本更可取,但boost变体有一些开销,特别是在拷贝构造和内存方面

常见的定制方法是以下修改的Factory模式:

  • 为泛型对象创建一个基本接口,该接口也封装对象类型(作为枚举),或使用“typeid”(首选)
  • 现在,使用模板
    派生类
    实现接口
  • 使用带有签名的模板化
    Create
    函数创建factory类:
  • 模板库*Factory::create()

    这将在堆上内部创建一个
    派生的
    对象,并重新运行一个动态强制转换指针。为您想要实现的每个类专门化它

    最后,定义一个
    变量
    包装器,它包含这个
    Base*
    指针,并定义模板get和set函数。诸如
    getType()
    isEmpty()
    、赋值和相等运算符等实用函数可以在此处适当实现


    取决于实用程序函数和工厂实现,受支持的类将需要支持一些基本函数,如赋值或复制构造。

    尽管这个问题已经回答了很长时间,但我要指出的是,在Qt库中也会这样做

    因为C++禁止联盟包含非默认类型 构造函数或析构函数,最有趣的Qt类不能是 用于工会。如果没有QVariant,这将是一个问题 QObject::property()和用于数据库工作等

    QVariant对象一次保存一个类型()的单个值。 (某些类型()是多值的,例如字符串列表。)您可以 找出变量的类型T,并将其转换为其他类型 使用convert()键入,使用toT()函数之一获取其值 (例如toSize())并检查该类型是否可以转换为 使用canConvert()的特定类型


    C++17现在有了
    std::variant
    ,这正是您想要的

    类模板std::variant表示类型安全的联合。一 在任何给定时间,std::variant的实例都会持有一个值 或在出现错误的情况下-无值(此 状态很难实现,请逐个查看无价值(例外)

    与联合一样,如果变量包含某个对象类型T的值,则 T的对象表示直接在对象中分配 变体本身的表示。不允许使用变体 分配额外(动态)内存


    我可以建议你用描述性问题来表达你的标题吗?也许类似于“如何在C++中存储变量数据?”我想你会得到更多的回应!嗯……我马上就明白了标题。这是一个非常优雅的解决方案……如果你对使用原始内存感到满意的话。我不同意空指针是优雅的。你正在绕过类型系统,这不是一个舒适地使用原始内存的问题,而是一个尽可能从编译器获得所有帮助的问题。如果你知道你在做什么,绕过类型系统是可以的。C++/C并不是100%类型化的。对于C
    ++
    ,void*指针是纯粹的邪恶。尽管原始指针有很多缺点,但你认为你不会变得更糟。事实证明你可以。。。1.它绕过了类型检查。即使使用枚举(例如,
    if(myType==MY_CLASS){MYCLASS*val=(MYCLASS*)(voidPtr);}
    ,多态MYCLASS也会对内存造成严重破坏。使用基类指针和动态强制转换稍微好一些。2.剪接删除的可能性(无法检查).3.建议的“双重”解决方案存在endian依赖性。这就好比说乌干达的法律不一致,存在漏洞,因此它是非法的,我有理由在那里犯下谋杀罪。尽管C/C++的类型系统不是傻瓜式的,使用指针、C风格的类型转换和重新解释可以让你四处走动。这并不意味着你把每一条规则/建议都扔出窗外。(对乌干达人没有冒犯。)