3 votes

Données hiérarchiques en C++

Comment puis-je gérer les données en C++ comme dans les nouveaux langages dynamiques, par exemple les tableaux en PHP sont très bien conçus :

$arr = array(

"somedata" => "Hello, yo, me being a simple string",

"somearray" => array(6 => 5, 13 => 9, "a" => 42),

"simple_data_again" => 198792,

);

Je suis ouvert à toutes les suggestions.

4voto

Alex B Points 34304

Le C++ ne fournit pas de support intégré pour les données hiérarchiques typées dynamiquement, mais vous pouvez en construire un à partir de primitives de niveau inférieur ou utiliser une bibliothèque tierce, par exemple :

  1. std::map avec boost::variant o boost::any comme catégorie de valeur.
  2. boost::property_tree

4voto

Matthieu M. Points 101624

Bien que je comprenne l'attrait des langages typés dynamiquement, cela ne convient pas bien au C++.

Le C++ est typée statiquement, ce qui signifie que le compilateur sait quel sera le type d'une variable et peut donc la traiter en toute sécurité.

Il existe des moyens d'émuler le typage dynamique (utilisation de Boost.Any par exemple), mais la vraie question est : POURQUOI ?

Si vous avez besoin de typage dynamique et/ou de réflexion, utilisez un langage qui les prend en charge, vous serez mieux servi.

Si vous voulez ou avez besoin du C++, apprenez à programmer en C++ au lieu d'essayer de porter PHP mot pour mot.

La plupart des langues peuvent servir le même objectif, cela ne signifie pas que les choses sont traitées de la même manière sous le noyau. Il est frustrant (dans le meilleur des cas) d'essayer de porter un langage vers un autre, déclaration par déclaration.

4voto

missingfaktor Points 44003

Si vous savoir à l'avance ce que toutes sortes de valeurs map va tenir, alors utilisez boost::variant . Ou bien, utilisez boost::any . Avec boost::any vous pourrez ensuite ajouter des entrées avec tout type de valeur sur la carte.


Exemple de code avec boost::variant :

Création d'une carte :

typedef boost::variant<std::string, std::map<int, int>, int> MyVariantType;
std::map<std::string, MyVariantType> hash;

Ajout d'entrées :

hash["somedata"] = "Hello, yo, me being a simple string";
std::map<int, int> temp; 
temp[6] = 5; 
temp[13] = 9;
hash["somearray"] = temp;
hash["simple_data_again"] = 198792;

Récupération des valeurs :

std::string s = boost::get<std::string>(hash["somedata"]);
int i = boost::get<int>(hash["simple_data_again"]);

Comme l'a souligné @Matthieu M dans les commentaires, le type de clé de la carte peut être une boost::variant . Cela devient possible parce que boost::variant fournit une valeur par défaut operator< L'implémentation fournissant les types qui la composent le font tous.


Exemple de code avec boost::any :

Création d'une carte :

std::map<std::string, boost::any> hash;

Ajout d'entrées :

hash["somedata"] = "Hello, yo, me being a simple string";
std::map<int, int> temp; 
temp[6] = 5; 
temp[13] = 9;
hash["somearray"] = temp;
hash["simple_data_again"] = 198792;

Récupération des valeurs :

std::string s = boost::any_cast<std::string>(hash["somedata"]);
int i = boost::any_cast<int>(hash["simple_data_again"]);

Ainsi, avec l'aide de boost::any le type de valeur de votre carte peut être dynamique (en quelque sorte). Le type de clé est toujours statique, et je ne connais pas de moyen de le rendre dynamique.


Un conseil :

Le C++ est un langage à typage statique. Les idiomes comme celui de votre message, qui sont utilisés assez souvent dans les langages dynamiques, ne conviennent pas bien au langage C++. Aller à l'encontre du grain d'un langage est une recette pour la douleur.

Je vous conseille donc de ne pas essayer d'émuler les idiomes de vos langages dynamiques préférés en C++. Apprenez plutôt les façons de faire du C++, et essayez de les appliquer à votre problème spécifique.


Références :

2voto

Lazarus Points 17526

Jetez un coup d'œil à "map" en C++, il y a un bon article sur Wikipedia. aquí .

1voto

Paul Michalik Points 3060

boost::variant peut contenir une "union de types", pour être plus exact. Voici un exemple de la façon dont vous pourriez définir une expression similaire à celle demandée :

std::map
<
 std::string,
 boost::variant
 <
  std::string,
  std::array<int, 4>,
  int
 >
> my_variant_array;

my_variant_array["somedata"] = "Hello, yo, me being a simple string";
my_variant_array["somearray"] = {
 1, 2, 3, 4
};
my_variant_array["simple_data_again"] = 198792;

Vous pourriez même définir une variation récursive d'une telle structure contenant une autre std::map de boost::variant . Sachez qu'il s'agit de quelque chose de différent de ce que vous avez probablement à l'esprit : boost::variant est une union sûre de types avec des valeurs associées. Vous pourriez l'utiliser pour implémenter un compilateur pour un langage dynamique qui autoriserait les constructions comme vous le demandez. c++ per se n'est pas dynamique - tout doit être fortement typé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X