C ++ stores multiple data types in one collection

Problem: I want disparate sections of my code to have access to a common collection that stores objects of different types in such a way that the type of each object is known and, to a decisive extent, retrieving from the collection should check the type at compile time. (I understand that this is close to the question asked earlier, but please read, this is somewhat more specific.)

To give a concrete example, I would like to do something as follows:

// Stuff that can go in the collection: enum Key { NUM_APPLES /* (unsigned int) */, APPLE_SIZE /* (double) */ } map<Key, Something> collection; unsigned int * nApples = collection.find(NUM_APPLES); int * appleSize = collection.find(APPLE_SIZE); // COMPILATION ERROR - WRONG TYPE 

My solution: So far, I have developed the following solution using boost::any :

Key:

 using namespace std; using namespace boost::any; struct KeySupertype { protected: // Can't create an instance of this type KeySupertype() {} private: // Can't copy KeySupertype& operator = (const KeySupertype& other) {} KeySupertype(const KeySupertype& other) {} }; template <typename Type> struct Key : public KeySupertype { public: Key() {} }; 

Collection:

 class PropertiesMap { public: template<typename T> T * find(Key<T> & key); /* Skipping erase, insert and other methods for brevity. */ private: map<const KeySupertype *, any> myAnyMap; }; template <typename T> T * PropertiesMap::find(Key<T> & key) { const map<const KeySupertype *, any>::iterator it = myAnyMap.find(&key); if(it == myAnyMap.end()) return NULL; return any_cast<T>(&it->second); } 

Using:

 static const Key<unsigned int> NUM_APPLES; static const Key<double> APPLE_SIZE; PropertiesMap collection; /* ...insert num apples and apple size into collection ...*/ unsigned int * const nApples = collection.find(NUM_APPLES); int * const nApples = collection.find(NUM_APPLES); // COMPILATION ERROR 

This type of type information is encoded with each Key in accordance with its template parameter, so the type will be used when interacting with the collection.

Questions:

1) Is this a reasonable way to achieve my goal?

2) The nasty point is that the collection uses the address of Key objects as an internal std::map key. Is there any way around this? Or at least a way to mitigate abuse? I tried to use a unique int in each key that was generated from static int (and does type std::map type int ), but I would like to avoid statics, if possible, to explain the flows.

3) To avoid using boost::any , would it be wise to have a type std::map type <const KeySupertype *, void *> and use static_cast<T> instead of any_cast ?

+4
source share
1 answer

1) Sounds like a smart decision to me

2) I think you are afraid that someone will copy the key and its address will change. If this is your problem, save the "original address" field in KeySuperType . During construction, set the source address for it, during copying, set the source address to the source address of the right hand (source). Use this original address to access the contents of the map. I really could not come up with a solution for compilation because at compile time the compilation units would not know about each other. You can assign a unique identifier to the keys at the earliest time of the link, and getting the address of global variables is equivalent to this. The only weak point that I see in this solution is that you define the same key in two dynamic shared libraries without extern , they will silently have their own versions of the key with different addresses. Of course, if everything goes to the same binary, you will not have this problem, since two declarations without extern will cause a "multiple declaration" linker error.

3) If your problem with boost::any depends on boost (which is more normal, then you think), then implement any yourself, this is surprisingly simple. If the issue is performance, then static_cast<> also seems good to me if you keep the insides of your PropertiesMap from those who don't know what they are doing ...

0
source

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


All Articles