2017-10-01 7 views
1

J'essaye de créer une classe qui peut mapper des chaînes à certains objets arbitraires ou même à des types primitifs. Pour clarifier, je ne parle pas d'un seul type générique, mais différents types, de sorte que la carte pourrait ressembler à ceci: ["speed": 3, "useNormal": false, "normal": Vec3()]C++ mappe la chaîne à l'objet

Une approche que j'ai essayé était de créer une struct BaseObject et d'en tirer les autres classes comme IntObject et FloatObject à partir de celui-ci. De cette façon, j'ai été en mesure de créer un std::map<std::string, BaseObject*>. Mais cette approche semble maladroite et les getters et setters pour la carte ont besoin d'un boîtier de commutation pour chaque type.

Quelqu'un a suggéré d'utiliser des octets. Fondamentalement, cela signifie sérialiser et désérialiser l'objet en tableaux d'octets et donc la carte ressemblerait à ceci: std::map<std::string, byte*>. Mais avec cette approche, le grand obstacle à surmonter est de générer en quelque sorte un objet d'un certain type à partir d'un tableau d'octets, que je ne sais pas comment faire.

Une autre suggestion était également d'utiliser des variants C++ 17. Mais c'est trop nouveau pour être largement soutenu.

J'apprécierais n'importe quelle sorte d'entrée!

+0

Lorsque vous prenez valeurs hors de la carte, comment sauriez-vous quel type utiliser? C'est à dire. est-il possible de connaître le type, disons, 'your_map [" key "]'. –

+1

jeter un oeil à http://www.boost.org/doc/libs/1_61_0/doc/html/any/s02.html –

+0

utiliser unorderedmap? http://www.cplusplus.com/reference/unordered_map/unordered_map/ – Alander

Répondre

2

Il y a un consentement général que std::map<std::string, std::any>> serait la meilleure solution pour cela. Mais depuis que je suis en train d'éviter stimuler et C++ 17, voici un pur C++ la mise en œuvre d'une approche orientée objet à ce problème:

struct SuperObject {}; 

template<class T> 
struct BaseObject: SuperObject { 
    T _value; 
    BaseObject(T value) : _value(value) {} 
}; 

std::unordered_map<std::string, SuperObject*> objectMap; 


template<typename T> 
void setValue(std::string name, T value) { 
    objectMap[name] = new BaseObject<T>(value); 
} 

template <typename T> 
T getValue(const std::string& name) { 
    return ((BaseObject<T>*)(objectMap[name]))->_value; 
} 

S'il vous plaît l'esprit l'énorme fuite de mémoire lors de l'appel setValue()