Evyatar
Evyatar

Reputation: 1157

Map to any struct

I'm using c++.
I want to create a map to store any struct in my project.
I.e I have the structers:

struct My_Struct1{ int x;}
struct My_Struct2{float y;}
...

And i want to declare a map:

MyMap[MessageID1] = My_Struct1_obj;
MyMap[MessageID2] = My_Struct2_obj;
....


Which type the MyMap should be?

map<unsigned int, ? > MyMap;

If i do map<unsigned int, void* > how i can know if i want to access to int x or to float y ? I need to do switch case on MessageID?

After i have got the message i want to copy some data from the match block..

Upvotes: 1

Views: 99

Answers (3)

A.B.
A.B.

Reputation: 1604

You can achieve that via inheritance, create a base struct and inherit both of your structs from that base struct (place some constructor to initialize the data member if you want).

//Your base struct
struct My_Base
{
    virtual void foo() {};
};

struct My_Struct1: virtual My_Base
{
public:
    int x;
    My_Struct1(int _x) { x = _x; }
};

struct My_Struct2 : virtual My_Base
{
public:
    float y;
    My_Struct2(float _y) { y = _y; }
};

map<unsigned int, My_Base*> _map;

To make it easily understandable, providing the driver or invocation code below.

My_Base* obj1 = new My_Struct1(2);
My_Base* obj2 = new My_Struct2(3.2f);

//Adding some random test data to map
_map[1] = obj1;
_map[2] = obj2;

My_Base* mapObjBase = _map.find(2)->second;
//Downcast the object you retrieved from the map, this downcasting could fail so please note the if here.
if (My_Struct2* mapObj2 = dynamic_cast<My_Struct2*>(mapObjBase))
{
    cout << "My_Struct2.y = " << mapObj2->y << endl;
}
else
{
    cout << "Error..." << endl;
}
//Some memory cleaning before leaving the code block.
delete obj1;
delete obj2;

Something about dynamic_cast (if you are interested in further reading...)

Upvotes: 3

rodrigo
rodrigo

Reputation: 98446

The easier way would be to create a base class for all your structures and store pointers to that in the map.

struct BaseStruct
{
    virtual ~BaseStruct()
    {}
};
struct My_Struct1 : BaseStruct { int x; }
struct My_Struct2 : BaseStruct { float y; }

std::map<unsigned int, BaseStruct *> MyMap;

Or you may prefer using a smart pointer to handle the lifetime of the objects.

std::map<unsigned int, std::shared_ptr<BaseStruct> > MyMap2;
std::map<unsigned int, std::unique_ptr<BaseStruct> > MyMap3;

Note the virtual destructor. That is important so that when you delete the objects from the map the memory of the subclasses is properly freed.

PS: Take a look at boost::any. It may be useful if you don't want or can't use the base struct.

Upvotes: 4

CodeFuller
CodeFuller

Reputation: 31312

You should declare struct type in following way:

struct My_Struct
{
    union
    {
        int x;
        float y;
    };
};

Then you can use it in following way:

map<unsigned int, My_Struct> MyMap;

Upvotes: 2

Related Questions