(Questions générales :
- Connaitre le TYPE des arguments multiples.
- Afficher la VALEUR d'une variable depuis une MACRO.
)
Bonjour, j'ai un petit soucis (ou plutôt une question) sur un programme que je programme en C++.
Mon objectif ici est d'écrire le moins de ligne de code possible.
J'ai plusieurs méthodes, qui prennent toutes un nombre fixe d'arguments. Les méthodes en question font en revanche toujours la même chose : Stocker les arguments dans une (std::map<string,string>).
Exemple :
La macro MAP_VARGS fait la chose suivante :Code:
1
2
3
4
5
6
7
8
9
10
11 #define ARG_LIST_STR(...) getArgNameArray(#__VA_ARGS__) #define MAP_VARGS(...) index_vargs(ARG_LIST_STR(__VA_ARGS__), ##__VA_ARGS__ ) Objet* Classe::ma_fonction_1( int count, float camembert, float max_id, bool hide ) { Objet* obj = new Objet(); obj->ajouterMap( MAP_VARGS(count,camembert,max_id,hide) ); return obj; } Objet* Classe::ma_fonction_2( bool calories, int roquefort, bool hide ) {....}
1. Liste le NOM des paramètres de la fonction pour les stocker en tant que clés dans un std::map<string,string>
2. Indexe les VALEURS des paramètres en tant que valeurs correspondantes dans le std::map<string,string>
J'obtiens donc une std::map contenant :
"count" -> valeur_count
"camembert" -> valeur_camembert
etc...
Je bloque actuellement sur la partie 2, car j'utilise les fonctionnalités de <stdvargs>, qui permet de passer un nombre variable d'arguments à une fonction. Le soucis, c'est que <stdvargs> est limité : On ne peut pas connaître le type des arguments à l'avance (pour cause, ce n'est stocké nulle part pendant l'exécution du programme).
J'écarte la solution de "caster" les arguments jusqu'à trouver le plus "convenable", car selon les compilateurs/architectures, je risquerais d'avoir des résultats différents. (tailles des types des variables)
Ma fonction pour les v_args :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 std::map<std::string,std::string> index_vargs( std::vector<std::string> keys, ... ) { std::map<std::string,std::string> parameters; va_list list; va_start(list,keys); for( int i=0; i<keys.size(); i++) { int p = va_arg(list,int); if ( p != N_UN ) { parameters[keys.at(i)] = otos(p); // otos() est une fonction convertissant n'importe quel type CONNU en string. } } va_end(list); return parameters; }
Pour l'instant, je pense que le meilleur moyen serait de "convertir" tous les arguments en std::string ( avec otos() ) AVANT de les passer dans la fonction v_args, mais comme je ne sais pas quel nombre d'arguments convertir à l'avance, le serpent se mord la queue ... :/
Une méthode qui marche :
--> En gros je fais la même chose, mais en passant chaque argument manuellement, après les avoir convertis en string.Code:
1
2
3
4
5
6
7
8
9 #define ARG_LIST_STR(...) getArgNameArray(#__VA_ARGS__) #define MAP_VARGS(...) index_vargs(ARG_LIST_STR(__VA_ARGS__), ##__VA_ARGS__ ) Objet* Classe::ma_fonction_1( int count, float camembert, float max_id, bool hide ) { Objet* obj = new Objet(); obj->ajouterMap( index_vargs(ARG_LIST_STR(count,camembert,max_id,hide)), otos(count),otos(camember),otos(max_id),otos(hide)); return obj; }
Le problème, c'est que mon objectif est d'éviter ce genre de répétitions inutiles. (il y aura environ 50 fonctions du type "ma_fonction_1"). Je suis sûr qu'il existe des MACROS portables qui permettent plus ou moins d'éviter ça, mais malgré mes recherches, je n'ai rien trouvé.
J'en appelle donc à votre aide, pour savoir s'il existe des "hacks" (portables), ou si quelquechose m'a échappé.
++ A noter que je ne cherche pas de moyen "dynamique" de résoudre mon problème, mais bien un moyen de "découvrir" le type des variables PENDANT LA COMPILATION.
(l'autre solution serait de générer mon code à partir d'un autre langage, vu que chaque fonction doit se comporter quasiment de la même façon)
Merci d'avance pour votre aide. Je suis à votre dispo' pour toute explication/éclaircissement.