Templatized Stocker plusieurs types différents dans std :: vector

merci à tous pour votre temps, je l’apprécie vraiment.

Il existe un besoin de stocker plusieurs variables de types différents dans un std :: vector en utilisant un modèle. Pour utiliser les fonctions suivantes, le programmeur doit savoir dans quel ordre il a stocké les variables et combien de variables ont été stockées.

class _NetVar {}; 

Une sous-classe est créée pour contenir la variable réelle:

 template  class NetVar : public _NetVar { private: VARTYPE Var; NetVar(VARTYPE Value) { Var = Value; } }; 

Un vecteur est créé de la classe d’assistance de base

 std::vector DataVec; 

Les données sont placées dans le vecteur comme suit:

 template  void AddData(DATATYPE AddData) { DataVec.push_back(NetVar(AddData)); } 

Les données sont extraites du vecteur ici, une variable interne conserve la position actuelle du vecteur et est incrémentée chaque fois qu’une variable est demandée:

 template  DATATYPE GetData() { NetVar Temp = PacketData[VecPos]; return Temp.Var; ++VecPos; } 

La fonction précédente est à l’origine du problème: il est possible de reconnaître la sous-classe en tant que classe de base, mais est-il possible de reconnaître la classe de base en tant que l’une de ses sous-classes?

Voici comment le code est utilisé:

 AddData(32); AddData(true); AddData("Test"); auto Var1 = GetData(); auto Var2 = GetData(); auto Var3 = GetData(); 

Lorsque GetData est appelé, une exception est levée:

 'initializing' : cannot convert from '_NetVar' to 'NetVar' 

Si quelqu’un pouvait m’aider, cela serait grandement apprécié, merci encore pour votre temps.

Remarque: Les bibliothèques externes telles que Boost doivent être évitées.

Le vecteur devrait être:

 std::vector<_netvar *> DataVec; 

ou un pointeur de haut niveau

 std::vector > DataVec; 

afin que vous puissiez stocker des instances des classes enfants au lieu de les découper en tranches vers la classe de base.

Sur GetData, vous devez convertir en amont le pointeur extrait du vecteur.


Edit: Ajouter un code de travail complet

Exemple travaillant sur ideone , a dû bricoler un peu les permissions.

et l’exemple va avec quelques commentaires ajoutés.

 #include  #include  #include  class _NetVar {}; template  class NetVar : public _NetVar { private: VARTYPE Var; public: NetVar(VARTYPE Value) { Var = Value; } }; 

Notez que j’ai changé le constructeur NetVar <> et l’attribut Var en public … AddData et GetData nécessaires pour y accéder.

Vous ne savez pas si, dans votre exemple, vous aviez des méthodes virtuelles sur _NetVar (auquel cas le static_pointer_cast ci-dessous pourrait être un dynamic_pointer_cast )

Dans le même ordre d’idées, vous voudrez peut-être vérifier que les destructeurs de NetVar (et pas seulement les destructeurs de _NetVar) sont appelés (coché dans ideone, ils fonctionnent dans mon exemple car j’utilise std::make_shared >(...) )

 std::vector > DataVec; int VecPos; 

Ajout de ces variables globales pour que les fonctions ci-dessous fonctionnent.

 template  void AddData(DATATYPE AddData) { DataVec.push_back(std::make_shared >(AddData)); } 

Nous créons donc ici un shared_ptr avec le nouvel object NetVar et le NetVar dans le vecteur.

 template  DATATYPE GetData() { std::shared_ptr<_netvar> content = DataVec[VecPos]; std::shared_ptr > Temp = std::static_pointer_cast >(content); ++VecPos; return Temp->Var; } 

Ici, le contenu du vecteur est std::shared_ptr<_netvar> , c’est ce que nous obtenons. Ce shared_ptr doit être converti au bon type de shared_ptr

Vous devez maintenant connaître le bon type de personnes à convertir en amont, sinon le comportement n’est pas défini. Si vous aviez des méthodes virtuelles, vous pouvez utiliser dynamic_pointer_cast, puis effectuer une vérification de null … mais cela entraîne certaines pénalités de performances.

 int main() { AddData(32); AddData(true); AddData("Test"); auto Var1 = GetData(); auto Var2 = GetData(); auto Var3 = GetData(); std::cout << Var1 << std::endl; std::cout << Var2 << std::endl; std::cout << Var3 << std::endl; return 0; } 

Enfin tester et imprimer les résultats.

Une solution consiste à supprimer _NetVar et à utiliser Boost.Any , comme dans:

 std::vector DataVec; template void AddData(T data) { DataVec.emplace_back(std::move(data)); } template T GetData() { return boost::any_cast(DataVec[VecPos++]); } AddData(32); AddData(true); AddData(std::ssortingng("test")); auto Var1 = GetData(); auto Var2 = GetData(); auto Var3 = GetData();