代码之家  ›  专栏  ›  技术社区  ›  Patrick

在C++中存储泛型值及其类型:合并类型+值在一个类中或分离它们?

  •  0
  • Patrick  · 技术社区  · 14 年前

    union Value
       {
       const char *str;
       double d;
       long l;
       short s;
       bool b;
       void *reference;
       };
    

    联合还允许存储更复杂的数据类型(如枚举、对实例的引用等),但所有数据都存储在值联合的一个成员中。

    由于数据类型可能很复杂,因此该类型目前存储在一个单独的结构中,如下所示:

    struct Type
       {
       short BaseType;            // one of TYPE_STRING, TYPE_LONG, TYPE_DOUBLE, ...
       char *referenceName;       // only used if BaseType==TYPE_REFERENCE
       Enumeration *enumeration;  // only used if BaseType==TYPE_ENUMERATION
       };
    

    在重新构造应用程序时,我考虑将两个结构集成到一个类中。然后,值将成为一个纯接口IValue,并且每个不同类型都有子类/实现。

    集成值和类型的缺点是,不能再简单地复制值,但它始终需要克隆。这样做的好处是你保证永远不会再丢失值的类型。

    如果我将值和类型保持为单独的类,我仍然会将类型从一个结构更改为层次结构。IType是接口,对于每个类型都有一个子类/实现,例如StringType、DoubleType、LongType。。。即使是髓鞘型,髓鞘型。。。然后,IType的实现可以决定在值联合中使用哪个值。

    尽管复制类型仍然需要克隆,但我至少可以在没有克隆的情况下复制值。在大多数情况下,复制的值比复制的类型多得多。

    当值和类型保持分离时,整个概念是可以根据需要多次复制值,但如果要获得实际的基础值,则需要类型。

    虽然应用程序是纯C++(NO.NET),但我愿意使用.NET作为我的开发的灵感,我注意到.NET中也有可以很容易在堆栈上创建的值,通过值传递给函数,…不需要克隆。

    模板不是我的应用程序中的解决方案,因为这将使大约50%的应用程序模板化。

    问题:

    • 有人处理C++中的通用值和类型系统吗?
    • 是否还有其他参数用于将值和类型保持在单独的类中?
    • 是否还有将值和类型合并到一个类中的参数?
    3 回复  |  直到 14 年前
        1
  •  3
  •   Puppy    14 年前

    您应该使用boost::variant或boost::any。这就是他们的目的。使用它们并不意味着你必须模板你的整个解决方案。此外,如果您不需要类型之间动态的、运行时的差异,那么这就是模板的用途。正确工作的正确工具-这是静态方差的模板,动态方差的boost::variant。你没有必要也没有理由使用自己的动态打字系统。

        2
  •  2
  •   wheaties    14 年前

    听起来你是在试图重新实现一个变体。你看过B吗 oost::Any

    在模板前面,模板化50%的解决方案没有问题。它很好地解决了你面临的问题。模板特征是一个很好的发明:

    template<typename T>
    struct VarValue{
        VarValue(T _t) : m_T(_t){}
        typedef T value_type;
        T m_T;
    };
    

    然后typedef允许您毫无顾忌地使用包含的对象,而不必担心某些东西不知道它是什么变量类型。

        3
  •  0
  •   Stephane Rolland    14 年前

    据我所知,类型和值在同一个结构中,VARIANT。

    您应该在win sdk和ATL(CComVariant)中找到它们。

    例如。:

    struct tagVARIANT
        {
        union 
            {
            struct __tagVARIANT
                {
                VARTYPE vt;  // here is stored the type
                WORD wReserved1;
                WORD wReserved2;
                WORD wReserved3;
                union     // there the value
                    {
                    LONGLONG llVal;
                    LONG lVal;
                    BYTE bVal;
                    SHORT iVal;
                    FLOAT fltVal;
                    DOUBLE dblVal;
                    VARIANT_BOOL boolVal;
                    _VARIANT_BOOL bool;
                    SCODE scode;
                    CY cyVal;
                    DATE date;
                    BSTR bstrVal;
                    IUnknown *punkVal;
                    IDispatch *pdispVal;
                    SAFEARRAY *parray;
                    BYTE *pbVal;
                    SHORT *piVal;
                    LONG *plVal;
                    LONGLONG *pllVal;
                    FLOAT *pfltVal;
                    DOUBLE *pdblVal;
                    VARIANT_BOOL *pboolVal;
                    _VARIANT_BOOL *pbool;
                    SCODE *pscode;
                    CY *pcyVal;
                    DATE *pdate;
                    BSTR *pbstrVal;
                    IUnknown **ppunkVal;
                    IDispatch **ppdispVal;
                    SAFEARRAY **pparray;
                    VARIANT *pvarVal;
                    PVOID byref;
                    CHAR cVal;
                    USHORT uiVal;
                    ULONG ulVal;
                    ULONGLONG ullVal;
                    INT intVal;
                    UINT uintVal;
                    DECIMAL *pdecVal;
                    CHAR *pcVal;
                    USHORT *puiVal;
                    ULONG *pulVal;
                    ULONGLONG *pullVal;
                    INT *pintVal;
                    UINT *puintVal;
                    struct __tagBRECORD
                        {
                        PVOID pvRecord;
                        IRecordInfo *pRecInfo;
                        }   __VARIANT_NAME_4;
                    }   __VARIANT_NAME_3;
                }   __VARIANT_NAME_2;
            DECIMAL decVal;
            }   __VARIANT_NAME_1;
        } ;