Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I simplify this redundant C++ code?

Tags:

c++

There are two existing classes, one is SrcField which returns the concrete type value, and the other is a union DSTField, that defines the corresponding data type.

class SrcField
{
public:
    signed char     GetInt8();
    unsigned char   GetUInt8();
    short           GetInt16();
    unsigned short  GetUInt16();
    int             GetInt32();
    unsigned int    GetUInt32();
    float           GetFloat();
    double          GetDouble();
    bool            GetBool();
    DataType        GetType();
private:
    DataType m_type;
    DSTField m_data;
};

union DSTField
{
    signed char    m_int8;
    unsigned char  m_uint8;
    short          m_int16;
    unsigned short m_uint16;
    int            m_int32;
    unsigned int   m_uint32;
    float          m_float;
    double         m_double;
    bool           m_bool;
};

When I use both classes, the application is as below. It's very redundant; is there any good way to simplify it, such as templates, generic programming, etc?

int main()
{
    SrcField sf;
    DSTField df;

    switch(sf.GetType())
    {
    case TYPE_INT8:
        df.m_int8 = sf.GetInt8();
        break;
    case TYPE_UINT8:
        df.m_uint8 = sf.GetUInt8();
        break;
    case TYPE_INT16:
        df.m_int16 = sf.GetInt16();
        break;
    case TYPE_UINT16:
        df.m_uint16 = sf.GetUInt16();
        break;
    case TYPE_INT32:
        df.m_int32 = sf.GetInt32();
        break;
    case TYPE_UINT32:
        df.m_uint32 = sf.GetUInt32();
        break;
    case TYPE_FLOAT:
        df.m_float = sf.GetFloat();
        break;
    case TYPE_DOUBLE:
        df.m_double = sf.GetDouble();
        break;
    case TYPE_BOOL:
        df.m_bool = sf.GetBool();
        break;
    default:
        break;
    }
}
like image 261
freshyy Avatar asked May 26 '17 08:05

freshyy


1 Answers

Using std::variant your code would look like this:

#include <iostream>
#include <variant>

typedef std::variant<
    signed char,
    unsigned char,
    short,
    unsigned short,
    int,
    unsigned int,
    float,
    double,
    bool
> SrcField, DSTField;

int main()
{
    SrcField sf(97.0f);
    DSTField df;

    df = sf;

    if(auto pval = std::get_if<float>(&df))
      std::cout << "variant value: " << *pval << '\n'; 
    else 
      std::cout << "failed to get value!" << '\n';
}

Note: Since it's c++17, for previous versions I recommend to use boost::variant, boost::any or a header-only implementation of Any class (for example I use one based on this in my project)

like image 118
pergy Avatar answered Oct 15 '22 16:10

pergy