/* IFT1166 - démonstration #4 - exercice 1 02-octobre-2005 v1.00 M.Lokbani énoncé et corrigé à partir d'Anderson. commentaires supplémentaires sur #ifdef contact: lokbani@iro.umontreal.ca Cet exercice a pour but de vous familiariser avec la surdéfiniton de fonctions. Les ambiguïtés possibles et comment les résoudre. Copyright (C) 2005 Université de Montréal Département d'informatique et de Recherche Opérationnelle M. Lokbani -- Tous Droits Réservés -- All Rights Reserved -- Utilisation des ifdef au niveau du préprocesseur On peut utiliser ifdef pour forcer la compilation que d'un bloc en particulier. La syntaxe d'un ifdef est comme suit: #ifdef XYZ bloc si VRAI -A- #else bloc si FAUX -B- #endif Ainsi si la variable XYZ a été déclarée, le préprocesseur va activer le bloc -A-. Sinon (la condition est représentée par la directive #else) c'est le bloc -B-. La directive #endif est utilisée pour signifier la fin de la directive #ifdef. #ifndef XYZ bloc si VRAI -A- #else bloc si FAUX -B- #endif On peut utiliser l'inverse de ifdef qui est ifndef. Si la variable XYZ n'a pas été déclarée on exécute le bloc -A- sinon le bloc -B-. Comment déclarer une variable pour n'utiliser qu'un bloc vis-à-vis d'un autre? On peut le faire sur la ligne de commande en utilisant l'option -D, comme suit: g++ .... -DXYZ .... -DXYZ permet de déclarer la variable XYZ. Comme elle existe, l'instruction (#ifdef XYZ) retourne VRAI. La variable peut avoir un nom quelconque. Pour cet exercice, nous avons utilisé EXO_ORIG pour signifier la version originale de l'exercice. La commande à utiliser pour activer cette variable est comme suit: g++ -Wall -pedantic -Os -DEXO_ORIG -c demo4exo1sol.cpp -o demo4exo1sol.o */ #include int min(int, int); // minimum entre deux entiers #ifndef EXO_ORIG double min(int, double); // minimum entre un entier et un double double min(double, int); // minimum entre un double et un entier #endif double min(double, double); // minimum entre deux doubles using namespace std; int main(){ int m = 43, n = 56; double v = 6.5, w = 8.9; cout << min(m, n) << endl; // minimum entre deux entiers cout << min(v, w) << endl; // minimum entre un entier et un double cout << min(m, w) << endl; // minimum entre un double et un entier cout << min(v, n) << endl; // minimum entre deux doubles return 0; } int min(int a, int b) { // minimum entre deux entiers return a < b ? a : b; } #ifndef EXO_ORIG double min(int a, double b) { // minimum entre un entier et un double return a < b ? a : b; } double min(double a, int b) { // minimum entre un double et un entier return a < b ? a : b; } #endif double min(double a, double b) { // minimum entre deux doubles return a < b ? a : b; } /******************************************************************** >demo4exo1sol 43 6.5 8.9 6.5 >Exit code: 0 Remarques --------- 1. Avec seulement les deux prototypes (int, int) et (double, double), le compilateur signale des ambiguïtés possibles lors de l'appel à min(int, double) et min(double, int). La raison est que le compilateur peut soit faire la promotion d'un int vers un double ou bien "caster" un double vers un int. >g++ -Wall -pedantic -Os -DEXO_ORIG -c demo4exo1sol.cpp -o demo4exo1sol.o demo4exo1sol.cpp: In function `int main()': demo4exo1sol.cpp:81: call of overloaded `min(int&, double&)' is ambiguous demo4exo1sol.cpp:66: candidates are: int min(int, int) demo4exo1sol.cpp:71: double min(double, double) demo4exo1sol.cpp:82: call of overloaded `min(double&, int&)' is ambiguous demo4exo1sol.cpp:66: candidates are: int min(int, int) demo4exo1sol.cpp:71: double min(double, double) >Exit code: 1 2. En y introduisant 4 prototypes de la fonction min, ceci va permettre de résoudre les problèmes d'ambiguïté. En effet, aucun des appels n'a besoin de faire la promotion ou de "caster" un argument. */