Mixed type container in C ++ (similar to nsdictionary)

What I would like to do (in C ++) is to create the "Parameter" data type, which has a value of min and max. Then I would like to create a container for these types.

eg. I have the following code:

    template <typename T>
    class ParamT {
    public:
        ParamT() {
        }

        ParamT(T _value):value(_value) {
        }

        ParamT(T _value, T _vmin, T _vmax):value(_value), vmin(_vmin), vmax(_vmax) {
        }


        void setup(T vmin, T vmax) {
            this->vmin      = vmin;
            this->vmax      = vmax;
        }

        void setup(T value, T vmin, T vmax) {
            setup(vmin, vmax);
            setValue(value);
        }

        T operator=(const T & value) {
            setValue(value);
        }



        void setValue(T v) {
            value = v;
        }

        T getValue() {
            return value;
        }

        operator T() {
            return getValue();
        }

    protected:

        T       value;
        T       vmin;
        T       vmax;
    };

    typedef ParamT<int>     Int;
    typedef ParamT<float>   Float;
    typedef ParamT<bool>    Bool;

In an ideal world, my Api would be something like:

std::map<string, Param> params;
params["speed"] = PFloat(3.0f, 2.1f, 5.0f);
params["id"] = PInt(0, 1, 5);

or

params["speed"].setup(3.0f, 2.1f, 5.0f);
params["id"].setup(0, 1, 5);

and writing them down:

params["speed"] = 4.2f;
params["id"] = 1;

or

params["speed"].setValue(4.2f);
params["id].setValue(1);

and readings:

float speed = params["speed"];
int id = params["id"];

or

float speed = params["speed"].getValue();
int id = params["id"].getValue();

Of course, in the code above ParamT does not have a base class, so I cannot create a map. But even if I create a base class for it that ParamT extends, I obviously cannot have different getValues ​​() that return different types. I thought of many solutions, including setValueI (int i), setValuef (float f), int getValueI (), float getValueF () or a map for ints, a map for float, etc. But they all seem very unclean. Is it possible to implement the above API in C ++?

, int, float, bool .. ( ) .

+3
5

++, . Boost, . - ,

typedef boost::variant< int, float, bool > ParamT; 
class Param
{
   public:
      // initialize the variants
      Param(ParamT min, ParamT max, ParamT value)
       : m_Min(min), m_Max(max), m_Value(value) {}

      // example accessor
      template<typename OutT>
      const ParamT& value()
      {
          return boost::get<OutT>(m_Value);
      }
      // other accessors for min, max ...
   private:
      ParamT m_Min, m_Value, m_Max;
};



Param speed(-10.0f, 10.0f, 0.0f);
float speedValue = speed.value<float>();

, (, long, std::string, ), typedef ParamT; , - , float int, .

, -....

class ProxyValue
{
public:
  ProxyValue(ParamT& value) : m_Value(value) {}
  template<typename ValueT>
  operator ValueT()
  {
     return boost::get<ValueT>(m_Value);
  }
private:
  ParamT& m_Value;
};

() Param, . .

Param speed(-10.0f, 0, 10);
float speedValue = speed.value();

, - . . , , , . YMMV.

, , , , .

+2

, ? , , / ? .

, , - , . . , , .

, , ( ) , / . , , . . , boost . :. - boost.

, , GetValueAsInt/SetValueAsInt, . , ++ : void SetValue(int value) void SetValue(float value). ++ , .

Edit:

, , . , .

, ++, void* , . , .

"" Java/#

Edit:

, boost:: any.

, : ? , , . , , , . , .

+1

boost:: any ( ) boost:: variant ( ); boost:: program_options , . boost:: program_options, . , , ; , . , .

+1

, . , , . - , , . - , ++ . , switch(). - :

    enum DataTypeCode
    {
        UNKNOWN,
        INT,
        FLOAT
    };

    template <class DataType>
    DataTypeCode GetDataTypeCode()
    {
        return UNKNOWN;
    }

    template <>
    DataTypeCode GetDataTypeCode<int>()
    {
        return INT;
    }

    template <>
    DataTypeCode GetDataTypeCodE<float>(
    {
        return FLOAT;
    }

    class BaseParam
    {
    public:
        virtual ~BaseParam() {}
        virtual DataTypeCode GetDataTypeCode()=0;
    };

    template <class DataType>
    class Param : public BaseParam
    {
    public:
        DataTypeCode GetDataTypeCode()
        {
            return ::GetDataTypeCode<DataType>();
        }
    }

, :

    std::map<string,BaseParam*> Params

    Params["speed"]=new Param<float>(...)

    BaseParam* pMyParam=Params["speed"];
    switch (pMyParam->GetDataTypeCode())
    {
        case INT:
            //dosomething with int types
        case FLOAT:
            //dosomething with float types
    }

, . std::map<string, BaseParam*> , , . , API- , .

0

, ( -, ), . Param, Value s. int float ( , ).

    class Value
    {
    private:
        union 
        {
            int i,
            float f
        } val;

        DataTypeCode dtc;
    public
        Value() : val.i(0), dtc(INT) {}
        Value(int i) : val.i(i), dtc(INT) {}
        Value(float f) : val.f(f), dtc(FLOAT) {}
        Value& operator=(int i) 
        {
            val.i=i; 
            dtc=INT; 
            return *this;
        }

        Value& operator=(float f) 
        {
            val.f=f; 
            dtc=FLOAT; 
            return *this;
        }

        operator int() 
        {
            switch (dtc)
            {
                case INT: return val.i;
                case FLOAT: return (int)val.f;
            }
            return 0;
        }

        operator float()
        {
            switch (dtc)
            {
                case INT: return (float)val.i;
                case FLOAT: return val.f;
            }
            return 0;
        }
    }

    class Param
    {
    private:
        Value value, min, max 
    public:
        Param(Value value, Value min, Value max) : value(value), min(min), max(max) {}
    }

, , DataTypeCode, .

, , :

    std::map<string:Param> Params;

    Params["speed"]=Param(1.4,0.1,5.6)

    float speed=Params["speed"]

casting operators along with overloaded constructors and operators = functions are automatically converted between you types.

0
source

Source: https://habr.com/ru/post/1760827/


All Articles