当前位置:  开发笔记 > 编程语言 > 正文

C++ Variant

如何解决《C++Variant》经验,为你挑选了4个好方法。

我正在创建一个存储有关特定数据源的元数据的类.元数据以树形结构,与XML的结构非常相似.元数据值可以是整数,小数或字符串值.

我很好奇C++是否有一种很好的方法来存储这种情况的变体数据.我希望变体使用标准库,所以我避免使用可用的COM,Ole和SQL VARIANT类型.

我目前的解决方案看起来像这样:

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.

是否有人使用标准库实现或看到了更清晰的用于C++变体数据类型的东西?



1> Konrad Rudol..:

从C++ 17开始,就有了std::variant.

如果你还不能使用它,你可能想要Boost.Variant.用于建模多态性的类似但不同的类型由std::any(和,前C++ 17,Boost.Any)提供.

就像一个额外的指针,你可以寻找" 类型擦除 ".



2> Fox..:

虽然Konrad的答案(使用现有的标准化解决方案)肯定比编写自己的易受攻击的版本更好,但是boost变体有一些开销,特别是在复制构造和内存方面.

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

    为通用对象创建Base接口,该接口也封装对象类型(作为枚举)或使用'typeid'(首选).

    现在使用模板Derived类实现接口.

    使用create带签名的模板化函数创建工厂类:

template Base * Factory::create ();

这会Derived<_T>在堆内部创建一个对象,并返回一个动态转换指针.专门针对您想要实现的每个课程.

最后,定义一个Variant包含此Base *指针的包装器,并定义模板get和set函数.这里可以适当地实现诸如getType(),isEmpty()赋值和相等运算符等实用函数.

根据实用程序功能和工厂实现,受支持的类将需要支持一些基本功能,如赋值或复制构造.


:)每个API使用纳秒 - 根据我的经验,这样的基本实现加起来.

3> Paul Nathan..:

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


如果您知道自己在做什么,可以绕过类型系统.无论如何,C++/C都不是100%打字的.
这是一个非常优雅的解决方案......如果您愿意使用原始内存.
我不同意无效指针是优雅的.你绕过了类型系统,它不是一个熟悉原始内存的问题,而是从编译器获得所有可能的帮助.
对于C` ++`,void*指针是纯粹的邪恶.由于原始指针的所有缺点,你认为你不会变得更糟.事实证明你可以...... 1.它绕过了类型检查.即使使用枚举(例如`if(myType == MY_CLASS){MYCLASS*val =(MYCLASS*)(voidPtr);}`,多态MYCLASS也会对内存造成严重破坏.使用基类指针和动态强制转换稍微好一些.2.拼接删除的可能性(并且无法检查).3."双重"解决方案建议遭受字节顺序依赖.
这就像说乌干达的法律不一致并且有漏洞,所以它是无法无天的,我有理由在那里谋杀.授予C/C++的类型系统不是万无一失的,使用指针,C风格的类型转换和reinterpret_cast可以让你绕过.这并不意味着你将所有规则/推荐抛到窗外.(对乌干达人没有冒犯 - 这是一个例子)

4> Matt Klein..:

C++ 17现在std::variant正是您正在寻找的.

的std ::变种

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有