web-dev-qa-db-fra.com

Comment puis-je stocker des objets de types différents dans un conteneur C++?

Existe-t-il un conteneur C++ que je pourrais utiliser ou créer et pouvant contenir, par exemple, des types int et string et double? Le problème auquel je suis confronté est que chaque fois que j'essaie de peupler, par exemple, une carte, un vecteur ou une liste avec, par exemple, les éléments suivants:

int x;
string y;
double z;

Je suis limité au format:

list<int> mycountainer;
vector<string> mycontainer;

qui force mycontainer à ne comporter qu'un seul type.

Avant que quiconque ne suggère des génériques, cela ne fonctionnerait pas non plus, car les conteneurs standard vector et list fournis avec C++ sont déjà génériques - ils peuvent être conteneur pour tous les types mais ne peuvent pas contenir plusieurs types.

J'aimerais éviter d'utiliser Boost également, si possible - je le préférerais s'il existe un moyen simple de le coder moi-même.

[modifier] Hé mec, merci beaucoup pour vos suggestions - Je devrais expliquer comment je vais utiliser ce conteneur, mais c'est un peu compliqué, d'où la (grande) simplification ci-dessus. Je pense que la meilleure option à partir d’ici utilise le Boost. Merci encore.

24
Ramsey

Vous pouvez utiliser (ou ré-implémenter) boost::any et stocker des instances de boost::any dans un conteneur. Ce serait la solution la plus sûre, car boost::any a probablement traité la plupart des cas Edge et la complexité inhérente à la résolution de ce type de problème dans le cas général.

Si vous voulez faire quelque chose de rapide et de sale, créez une structure ou peut-être une union contenant des membres de tous les types potentiels avec une énumération ou un autre indicateur indiquant quel type est 'actif' dans l'objet. Soyez particulièrement prudent avec les syndicats car ils ont des propriétés intéressantes (par exemple, invoquer un comportement indéfini si vous lisez le mauvais membre de l'union, un seul des membres peut être «actif» à la fois, celui qui a été écrit le plus récemment).

Je suis curieux de savoir ce que vous faites si vous avez besoin d'une telle construction.

21
Josh

Eh bien, la première question serait:Pourquoi pensez-vous que vous avez besoin de stocker des objets de types différents et totalement non liés dans le même conteneur?Cela me semble louche. 

Si j'en avais le besoin, je regarderais dans boost::variant ou boost::any

13
sbi

Ce que vous voulez s'appelle un "conteneur hétérogène". C++ ne les prend pas techniquement en charge dans la STL, mais Boost le fait.

Etant donné cela, je pense que vous trouverez votre réponse dans cette question: comment faire une boostmap hétérogène

6
T.E.D.

Vous pouvez utiliser des structures, des classes ou std :: pair.

[modifier]

Pour les classes et les structs:

struct XYZ {
    int x;
    string y;
    double z;
};
std::vector<XYZ> container;

XYZ el;
el.x = 10;
el.y = "asd";
el.z = 1.123;
container.Push_back(el);

Pour std :: pair:

#include <pair>
typedef std::pair<int, std::pair<string, double> > XYZ;
std::vector<XYZ> container;
container.Push_back(std::make_pair(10, std::make_pair("asd", 1111.222)));
2
ssmir

Vous pouvez utiliser une structure qui contient les trois.

struct Data
{
    int intVal;
    std::string stringVal;
    double doubleVal;
};

Ensuite, vous pouvez simplement déclarer list mycontainer<Data> et utiliser la valeur appropriée, à condition de connaître le type de valeur. Si ce n'est pas le cas, ajoutez à la structure un champ d'addition vous indiquant lequel des trois types de données est utilisé.

struct Data
{
    enum DATATYPE { DT_INT, DT_STRING, DT_DOUBLE } type;

    int intVal;
    std::string stringVal;
    double doubleVal;
};

Si vous êtes préoccupé par l'utilisation de la mémoire, vous pouvez probablement utiliser une union, bien que j'aie tendance à éviter de l'utiliser. C'est peut-être une paranoïa inutile de ma part cependant.

0
James

Si vous devez stocker un nombre limité d’éléments, placez-les dans une classe ou une structure.

S'il n'y a pas de limite aux éléments que vous auriez besoin de stocker dans ce conteneur, examinez une manière différente de procéder car le seul moyen de le faire est de les stocker en tant qu'objet, puis de les attribuer à leur propre type lorsque vous besoin d'y accéder.

Toutefois, si un élément peut potentiellement se trouver dans le conteneur, vous n’avez aucun moyen de savoir quels types d’éléments sont spécifiques au type dans le conteneur. Par conséquent, vous ne pourrez pas les lancer.

Si C++ contenait une réflexion, il y aurait peut-être un moyen de le faire, mais C++ n'a pas de réflexion.

0
jcvandan