2011-02-07 4 views
2

J'ai besoin d'un type variant qui contient des instances de toute classe définie par l'utilisateur. Donc, j'utilise void *:boost :: variant et void * pointers

typedef boost::variant<void*, int, float, std::string> Tvariant; 

J'ai créé une classe wrapper avec une carte:

typedef std::map<std::string, Tvariant> Tvalues; 

Exemple d'utilisation:

int x = 123; 
attributes.set("int_var", x); 
x = attributes.get<int>("int_var"); 

MyClass* obj = new MyClass(); 
attributes.set("void*_var", obj); 
obj = static_cast<MyClass*>(attributes.get<void*>("void*_var")); 
obj = attributes.cast<MyClass*>("void*_var"); // the same 

Il y a 2 problèmes avec ce vide * en variante:

  1. Copier des attributs avec des pointeurs sur dyna La mémoire allouée est dangereuse et sujette aux erreurs.
  2. L'utilisateur peut static_cast void * vers WrongClass *, pas vers MyClass *. Il compile, mais le résultat est imprévisible.

solutions possibles:

  1. Utiliser boost :: shared_ptr < void *>.
  2. Rappelez-vous de typeid pour toutes les valeurs void * (lorsqu'elles sont ajoutées) dans std::map<void*, typeid> typeid_map. Lorsque l'utilisateur demande la valeur void *, en la convertissant en TClass *, évaluons une assertion: assert(typeid_from_typeid_map == typeid(TClass*)).

Questions:
1. Y at-il d'autres solutions pour maintenir les valeurs de toutes les catégories définies par l'utilisateur?
2. Peut-être recommanderez-vous de meilleures solutions pour les problèmes mentionnés et signalez-vous d'autres problèmes?

Répondre

6

Avez-vous regardé Boost::Any? C'est quelque chose qui porte avec lui la connaissance du temps de la coulée du type tout en cachant quel type il est réellement via le Tout.

+0

Oui, mais boost :: any ne fournit pas de vérifications à la compilation et est plus lent que boost :: variant. Est-ce que boost :: any fournit une sécurité de type lors de la conversion de n'importe quelle valeur en classe définie par l'utilisateur? –

+0

@topright Comme vous utilisez déjà Boost, boost :: any semble le chemin à parcourir. – karlphillip

+2

@topright: 'boost :: any' fournit la vérification du type d'exécution, et' any_cast' vous demande de spécifier le type que vous voulez récupérer, par exemple. Myclass * c = any_cast (myMap ["myClassObj"]) ', qui lance' bad_any_cast' si vous avez eu tort sur le type. Puisque vous allez rechercher des valeurs dans une carte, je doute que le surcoût de boost: any soit pertinent pour vous. Boost any est syntaxiquement très propre et très sûr. –

Questions connexes