Les patrons de fonctions

Les patrons de fonctions

Définition d’un patron de fonctions

On précise les paramètres (muets) de type, en faisant précéder chacun du mot (relativement arbitraire) class sous la forme template . La définition de la fonction est classique, hormis le fait que les paramètres muets de type peuvent être employés n’importe où un type effectif est permis. exos_c++.book Page 251 Jeudi, 5. juillet 2007 11:10 11 Exercices en langage C++ 252 © Éditions Eyrolles Par exemple : template void fct (T a, T * b, U c) { T x ; // variable locale x de type T U * adr ; // variable locale adr de type U * … adr = new T [10] ; // allocation tableau de 10 éléments de type T … n = sizeof (T) ; // une instruction utilisant le type T … } Une instruction telle que (T désignant un type quelconque) : T x (3) ; est légale même si T n’est pas un type classe ; dans ce dernier cas, elle est simplement équivalente à : T x = 3 ; Instanciation d’une fonction patron Chaque fois qu’on utilise une fonction ayant un nom de patron, le compilateur cherche à utiliser ce patron pour créer (instancier) une fonction adéquate. Pour ce faire, il cherche à réaliser une correspondance absolue des types : aucune conversion, qu’il s’agisse de promotion numérique ou de conversion standard n’est permise ; qui plus est, les qualifieurs const et volatile doivent être exactement les mêmes. Voici des exemples utilisant notre patron précédent : int n, p ; float x ; char c ; int * adi ; float * adf ; class point ; point p ; point * adp ; fct (n, adi, x) ; // instancie la fonction void fct (int, int *, float) fct (n, adi, p) // instancie la fonction void fct (int, int *, int) fct (x, adf, p) ; // instancie la fonction void fct (float, float *, int) fct (c, adi, x) ; // erreur char et int * ne correspondent pas à T et T* // ( pas de conversion) fct (&n, &adi, x) ; // instancie la fonction void fct (int *, int * *, float) fct (p, adp, n) ; // instancie la fonction void fct (point, point *, int) D’une manière générale, il est nécessaire que chaque paramètre de type apparaisse au moins une fois dans l’en-tête du patron. 

Les patrons de fonctions

La définition d’un patron de fonctions ne peut pas être compilée seule ; de toute façon, elle doit être connue du compilateur pour qu’il puisse instancier la bonne fonction patron. En général, les définitions de patrons de fonctions figureront dans des fichiers d’extension h, de façon à éviter d’avoir à en fournir systématiquement la liste.

Les paramètres expression d’un patron de fonctions

Ils ont été introduits par la norme. Un paramètre expression d’un patron de fonctions se présente comme un argument usuel de fonction ; il n’apparaît pas dans la liste de paramètres de type (template) et il doit apparaître dans l’en-tête du patron. Par exemple : template int compte (T * tab, int n) { // ici, on peut se servir de la valeur de l’entier n // comme on le ferait dans n’importe quelle fonction ordinaire } Un patron de fonctions peut disposer d’un ou de plusieurs paramètres expression. Lors de l’appel, leur type n’a plus besoin de correspondre exactement à celui attendu : il suffit qu’il soit acceptable par affectation, comme dans n’importe quel appel d’une fonction ordinaire. Surdéfinition de patrons de fonctions et spécialisation de fonctions de patrons On peut définir plusieurs patrons de même nom, possédant des paramètres (de type ou expression) différents. La seule règle à respecter dans ce cas est que l’appel d’une fonction de ce nom ne doit pas conduire à une ambiguïté : un seul patron de fonctions doit pouvoir être utilisé à chaque fois. Par ailleurs, il est possible de fournir la définition d’une ou plusieurs fonctions particulières qui seront utilisées en lieu et place de celle instanciée par un patron. Par exemple, avec : template T min (T a, T b) // patron de fonctions { … } char * min (char * cha, char * chb) // version spécialisée pour le type char * { … } int n, p; char * adr1, * adr2 ; min (n, p) // appelle la fonction instanciée par le patron général // soit ici : int min (int, int) min (adr1, adr2) // appelle la fonction spécialisée // char * min (char *, char *)

Algorithme d’instanciation ou d’appel d’une fonction

Précisons comment doivent être aménagées les règles de recherche d’une fonction surdéfinie, dans le cas où il existe un ou plusieurs patrons de fonctions. Lors d’un appel de fonction, le compilateur recherche tout d’abord une correspondance exacte avec les fonctions « ordinaires ». S’il y a ambiguïté, la recherche échoue (comme à l’accoutumée). Si aucune fonction « ordinaire » ne convient, on examine alors tous les patrons ayant le nom voulu (en ne considérant que les paramètres de type). Si une seule correspondance exacte est trouvée, la fonction correspondante est instanciée (du moins, si elle ne l’a pas déjà été) et le problème est résolu. S’il y en a plusieurs, la recherche échoue. Enfin, si aucun patron de fonction ne convient, on examine à nouveau toutes les fonctions « ordinaires » en les traitant cette fois comme de simples fonctions surdéfinies (promotions numériques, conversions standard…).

Exercice 123

Ici, notre patron ne comportera qu’un seul paramètre de type (correspondant à la fois à l’unique argument et à la valeur de retour de la fonction). Sa définition ne pose pas de problème particulier. #include using namespace std ; template T carre (T a) { return a * a ; } main() { int n = 5 ; float x = 1.5 ; cout << « carre de  » << n <<  » =  » << carre (n) << « \n » ; cout << « carre de  » << x <<  » =  » << carre (x) << « \n » ; } Énoncé Créer un patron de fonctions permettant de calculer le carré d’une valeur de type quelconque (le résultat possédera le même type). Écrire un petit programme utilisant ce patron.

Exercice 124

L’appel I est correct ; il instancie la fonction : int fct (int, int, int) b. L’appel II est correct ; il instancie la fonction : int fct (int, float, int) c. L’appel III est incorrect. d. L’appel IV est correct selon la norme. Il instancie la fonction : char * fct (char *, int, char *) L’appelþIV n’était pas accepté dans la version 3 qui ne considérait pas char * comme une correspondance absolue pour char[20]. Énoncé Soit cette définition de patron de fonctions : template T fct (T a, U b, T c) { ….. } Avec les déclarations suivantes : int n, p, q ; float x ; char t[20] ; char c ; Quels sont les appels corrects et, dans ce cas, quels sont les prototypes des fonctions instanciées ? fct (n, p, q) ; // appel I fct (n, x, q) ; // appel II fct (x, n, q) ; // appel III fct (t, n, &c) ; // appel IV.

Formation et coursTélécharger le document complet

Télécharger aussi :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *