Section courante

A propos

Section administrative du site

 Langage  Elément  Tutoriel  Programmation  IDE  Annexe  Aide 
ABAP/4
Ada
Assembleur
Assembly & bytecode
ASP (Active Server Pages)
Basic
C
C++
C# (C Sharp)
Cobol
ColdFusion
Fortran
HTML
Java
JavaScript
LISP
Logo
LotusScript
Oberon
Pascal
Perl
PHP
PL/1
Prolog
Python
Rebol
REXX
Ruby
Rust
SAS
NoSQL
SQL
Swift
X++ (Axapta)
GNAT
SMALLAda
VHDL
Assembleur 370
Assembleur 1802
Assembleur 4004
Assembleur 6502
Assembleur 6800
Assembleur 68000
Assembleur 8080 et 8085
Assembleur 8089
Assembleur 80x86
Assembleur AGC4
Assembleur ARM
Assembleur DPS 8000
Assembleur i860
Assembleur Itanium
Assembleur MIPS
Assembleur PDP-11
Assembleur PowerPC
Assembleur RISC-V
Assembleur SPARC
Assembleur SuperH
Assembleur UNIVAC I
Assembleur VAX
Assembleur Z80
Assembleur Z8000
Assembleur z/Architecture
ASSEMBLER/MONITOR 64
Micol Assembler
GFA Assembler
A86
MASM (Macro Assembler)
TASM (Turbo Assembler)
CIL
Jasmin
LLVM
MSIL
Parrot
P-Code (PCode)
SWEET16
G-Pascal
ASP 1.0
ASP 2.0
ASP 3.0
ASP.NET
ASP.NET Core
ABasiC (Amiga)
Adam SmartBASIC
Altair BASIC
AmigaBASIC (Amiga)
AMOS Basic (Amiga)
Atari Basic (Atari 400, 600 XL, 800, 800XL)
Basic Apple II (Integer BASIC/APPLESOFT)
Basic Commodore 64 (CBM-BASIC)
Basic Commodore 128 (BASIC 7.0)
Basic Commodore VIC-20 (CBM-BASIC 2.0)
Basic Coco 1 (Color Basic)
Basic Coco 2 (Extended Color Basic)
Basic Coco 3 (Extended Color Basic 2.0)
BASICA (PC DOS)
Basic Pro
BBC BASIC
Blitz BASIC (Amiga)
DarkBASIC
Dartmouth BASIC
GFA-Basic (Atari ST/Amiga)
GWBASIC (MS-DOS)
Liberty BASIC
Locomotive BASIC (Amstrad CPC)
MSX-Basic
Omikron Basic (Atari ST)
Oric Extended Basic
Power Basic
Quick Basic/QBasic (MS-DOS)
Sinclair BASIC (ZX80, ZX81, ZX Spectrum)
ST BASIC (Atari ST)
Turbo Basic
Vintage BASIC
VBScript
Visual Basic (VB)
Visual Basic .NET (VB .NET)
Visual Basic pour DOS
Yabasic
BeckerBASIC
SIMONS' BASIC
Basic09 d'OS-9
Disk Extended Color Basic
Basic09 d'OS-9
Disk Extended Color Basic
Access
Excel
Visual Basic pour Windows
Visual Basic .NET pour Windows
C Shell Unix (csh)
C pour Amiga
C pour Atari ST
C pour DOS
C pour Falcon030
C pour GEMDOS (Atari ST)
C pour Linux
C pour PowerTV OS
C pour OS/2
C pour Unix
C pour Windows
Aztec C
CoCo-C
GNU C
HiSoft C
IBM C/2
Introl-C
Lattice C
Microsoft C
MinGW C
MSX-C
Open Watcom C
OS-9 C Compiler
Pure C
Quick C
Turbo C
HiSoft C for Atari ST
HiSoft C for CP/M (Amstrad CPC)
C++ pour OS/2
C++ pour Windows
Borland C++
C++Builder
IBM VisualAge C++
Intel C++
MinGW C++
Open Watcom C++
Symantec C++
Turbo C++
Visual C++
Visual C++ .NET
Watcom C++
Zortech C++
C# (C Sharp) pour Windows
Apple III Cobol
Microsoft Cobol
BlueDragon
Lucee
OpenBD
Railo
Smith Project
Microsoft Fortran
WATFOR-77
CSS
FBML
Open Graph
SVG
XML
XSL/XSLT
LESS
SASS
GCJ (GNU)
JSP
Jython
Visual J++
Node.js
TypeScript
AutoLISP
ACSLogo
LotusScript pour Windows
Amiga Oberon
Oberon .NET
Apple Pascal
Delphi/Kylix/Lazarus
Free Pascal
GNU Pascal
HighSpeed Pascal
IBM Personal Computer Pascal
Lisa Pascal
Maxon Pascal
MPW Pascal
OS-9 Pascal
OSS Personal Pascal
Pascal-86
Pascal du Cray Research
Pascal/VS
Pascal-XT
PURE Pascal
QuickPascal
RemObjets Chrome
Sun Pascal
THINK Pascal
Tiny Pascal (TRS-80)
Turbo Pascal
UCSD Pascal
VAX Pascal
Virtual Pascal
Turbo Pascal for CP/M-80
Turbo Pascal for DOS
Turbo Pascal for Macintosh
Turbo Pascal for Windows
CodeIgniter (Cadre d'application)
Drupal (Projet)
Joomla! (Projet)
Phalanger (PHP .NET)
phpBB (Projet)
Smarty (balise)
Twig (balise)
Symfony (Cadre d'application)
WordPress (Projet)
Zend (Cadre d'application)
PL360
PL/M-80
PL/M-86
Turbo Prolog
CPython
IronPython
Jython
PyPy
AREXX
Regina REXX
JMP
Btrieve
Cassandra
Clipper
CouchDB
dBASE
Hbase
Hypertable
MongoDB
Redis
Access
BigQuery
DB2
H2
Interbase
MySQL
Oracle
PostgreSQL
SAP HANA
SQL Server
Sybase
U-SQL
Introduction
Les remarques
Les opérateurs
Les instruction conditionnelles
Les instructions de boucles
Type de données
Définition de fonction
Référence de mots réservés (mots clefs)
Référence de procédures et fonctions
Les modules (Packages)
Les premiers pas
Les éléments lexicaux
Les déclarations et types
Les noms et les expressions
Les instructions
Les sous-programmes
Les paquets
Les règles de visibilité
Les tâches
Structure du programme et problèmes de compilation
Les exceptions
Les unités génériques
Clauses de représentation et fonctionnalités dépendantes de la mise en oeuvre
Les entrées-sorties
Bonjour
Biochimie
Géographie
Géométrie
Histoire
Mathématique
Médicale
Météorologie
Océanographie
Sport
Temps
Trigonométrie
Validation
Calcul du calcium corrigé
Distance en Km entre deux longitudes et latitudes
Aire d'un cercle
Aire d'une surface de prisme rectangulaire
Aire d'un triangle
Distance entre deux points
Chiffre romain
Ackermann
Exp
Factoriel
Fibonacci
Log
Nombre premier
Odd
Random
Sqrt
Triangle Pascal
Hauteur utérine
Unité de mesure
Fréquence des vagues
Hockey
Année bissextile
Date de la Pâque
Atn/ATan/ArcTan
Courriel
AdaGIDE
GNAT Programming Studio
SET's Editor
Attributs de langages prédéfinis
Les pragma de langage prédéfinis
Environnement de langage prédéfini
Référence de termes et du vocabulaire
Téléchargement
Préface
Notes légal
Dictionnaire
Recherche

Les unités génériques

Une unité générique est une unité de programme étant soit un sous-programme générique, soit un paquet générique. Une unité générique est un modèle, paramétré ou non, à partir duquel des sous-programmes ou paquets correspondants (non génériques) peuvent être obtenus. Les unités de programme résultantes sont dites instances de l'unité générique d'origine.

Une unité générique est déclarée par une déclaration générique. Cette forme de déclaration comporte une partie formelle générique déclarant tous les paramètres formels génériques. Une instance d'une unité générique est obtenue à la suite d'une instanciation générique avec des paramètres réels génériques appropriés pour les paramètres formels génériques. Une instance d'un sous-programme générique est un sous-programme. Une instance d'un paquet générique est un paquet.

Les unités génériques sont des modèles. En tant que modèles, elles n'ont pas les propriétés spécifiques à leurs homologues non génériques. Par exemple, un sous-programme générique peut être instancié mais ne peut pas être appelé. En revanche, l'instance d'un sous-programme générique est un sous-programme non générique; par conséquent, cette instance peut être appelée mais ne peut pas être utilisée pour produire d'autres instances.

Les déclarations génériques

Une déclaration générique déclare une unité générique, étant soit un sous-programme générique, soit un paquet générique. Une déclaration générique comprend une partie formelle générique déclarant tous les paramètres formels génériques. Un paramètre formel générique peut être un objet; en variante (contrairement à un paramètre d'un sous-programme), il peut être un type ou un sous-programme.

declaration_generique ::= specification_generique;

specification_generique ::=
     partie_formelle_generique specification_du_sous_programme
   | partie_formelle_generique specification_du_paquet

partie_formelle_generique ::= generic [declaration_de_parametre_generique]

declaration_de_parametre_generique ::=
     liste_identifiant : [in [out]] marque_type [:= expression];
   | type identifier is definition_de_type_generique;
   | declaration_de_type_prive
   | with specification_du_sous_programme [is nom];
   | with specification_du_sous_programme [is <>];

definition_de_type_generique ::=
     (<>) | intervalle <> | chiffres <> | delta <>
   | definition_du_type_de_tableau | définition_du_type_d_acces

Les termes objet formel générique (ou simplement objet de format), type formel générique (ou simplement type de format) et sous-programme formel générique (ou simplement sous-programme de format) sont utilisés pour désigner les paramètres formels génériques correspondants.

La seule forme d'indication de sous-type autorisée dans une partie formelle générique est une marque de type (c'est-à-dire que l'indication de sous-type ne doit pas inclure de contrainte explicite). Le désignateur d'un sous-programme générique doit être un identifiant.

En dehors de la spécification et du corps d'une unité générique, le nom de cette unité de programme désigne l'unité générique. En revanche, dans la région déclarative associée à un sous-programme générique, le nom de cette unité de programme désigne le sous-programme obtenu par l'instanciation actuelle de l'unité générique. De même, dans la région déclarative associée à un paquet générique, le nom de cette unité de programme désigne le paquet obtenu par l'instanciation actuelle.

L'élaboration d'une déclaration générique n'a aucun autre effet.

Exemples de parties de format génériques :

  1. generic                                          -- sans paramètre
  2.  
  3. generic
  4.   SIZE : NATURAL;                                -- objet formel
  5.   
  6. generic
  7.   LENGTH : INTEGER := 200;                       -- objet formel avec une expression par défaut
  8.   AREA   : INTEGER := LENGTH*LENGTH;             -- objet formel avec une expression par défaut
  9.  
  10. generic
  11.   type ITEM is private;                          -- type formel
  12.   type INDEX is (<>);                            -- type formel
  13.   type ROW is array(INDEX range <>) of ITEM;     -- type formel
  14.   with function "<"(X, Y : ITEM) return BOOLEAN; -- sous-programme formel

Exemples de déclarations génériques déclarant des sous-programmes génériques :

  1. generic
  2.   type ELEM is private;
  3. procedure EXCHANGE(U, V : in out ELEM);
  4.  
  5. generic
  6.   type ITEM is private;
  7.   with function "*"(U, V : ITEM) return ITEM is <>;
  8. function SQUARING(X : ITEM) return ITEM;

Exemple de déclaration générique déclarant un paquet générique :

  1. generic
  2.   type ITEM   is private;
  3.   type VECTOR is array (POSITIVE range <>) of ITEM;
  4.   with function SUM(X, Y : ITEM) return ITEM;
  5. package ON_VECTORS is
  6.   function SUM   (A, B : VECTOR) return VECTOR;
  7.   function SIGMA (A    : VECTOR) return ITEM;
  8.   LENGTH_ERROR : exception;
  9. end;

Remarques : Dans un sous-programme générique, le nom de cette unité de programme agit comme le nom d'un sous-programme. Ce nom peut donc être surchargé et il peut apparaître dans un appel récursif de l'instanciation courante. Pour la même raison, ce nom ne peut pas apparaître après le mot réservé new dans une instanciation générique (récursive).

Une expression apparaissant dans une partie formelle générique est soit l'expression par défaut d'un objet formel générique de mode in, soit un constituant d'un nom d'entrée donné comme nom par défaut pour un sous-programme formel, soit l'expression par défaut d'un paramètre d'un sous-programme formel. Les expressions par défaut pour les objets formels génériques et les noms par défaut pour les sous-programmes formels ne sont évalués que pour les instanciations génériques utilisant de telles valeurs par défaut. Les expressions par défaut pour les paramètres des sous-programmes formels ne sont évaluées que pour les appels des sous-programmes formels utilisant de telles valeurs par défaut. (Les règles de visibilité habituelles s'appliquent à tout nom utilisé dans une expression par défaut : l'entité désignée doit donc être visible à la place de l'expression.)

Ni les paramètres formels génériques ni leurs attributs ne sont autorisés à être des constituants d'expressions statiques.

Objets formels génériques

La première forme de déclaration de paramètre générique déclare des objets formels génériques. Le type d'un objet formel générique est le type de base du type désigné par la marque de type donnée dans la déclaration de paramètre générique. Une déclaration de paramètre générique avec plusieurs identifiants est équivalente à une séquence de déclarations de paramètres génériques simples.

Un objet formel générique a un mode étant soit in, soit in out. En l'absence d'indication de mode explicite dans une déclaration de paramètre générique, le mode in est supposé ; sinon, le mode est celui indiqué. Si une déclaration de paramètre générique se termine par une expression, l'expression est l'expression par défaut du paramètre formel générique. Une expression par défaut n'est autorisée que si le mode est in (que ce mode soit indiqué explicitement ou implicitement). Le type d'une expression par défaut doit être celui du paramètre formel générique correspondant.

Un objet formel générique de mode in est une constante dont la valeur est une copie de la valeur fournie comme paramètre générique actuel correspondant dans une instanciation générique. Le type d'un objet formel générique de mode in ne doit pas être un type limité; le sous-type d'un tel objet formel générique est le sous-type désigné par la marque de type donnée dans la déclaration de paramètre générique.

Un objet formel générique de mode in out est une variable et désigne l'objet fourni comme paramètre générique actuel correspondant dans une instanciation générique. Les contraintes s'appliquant à l'objet formel générique sont celles du paramètre générique actuel correspondant.

Remarque : les contraintes s'appliquant à un objet formel générique de mode in out sont celles du paramètre générique actuel correspondant (et non celles impliquées par la marque de type apparaissant dans la déclaration du paramètre générique). Dans la mesure du possible (pour éviter toute confusion), il est recommandé d'utiliser le nom d'un type de base pour la déclaration d'un tel objet formel. Si, toutefois, le type de base est anonyme, il est recommandé d'utiliser le nom du sous-type défini par la déclaration de type pour le type de base.

Types formels génériques

Une déclaration de paramètre générique incluant une définition de type générique ou une déclaration de type privé déclare un type formel générique. Un type formel générique désigne le sous-type fourni comme paramètre actuel correspondant dans une instanciation générique (d). Cependant, au sein d'une unité générique, un type formel générique est considéré comme distinct de tous les autres types (formels ou non formels). La forme de contrainte applicable à un type formel dans une indication de sous-type dépend de la classe du type comme pour un type non formel.

La seule forme d'intervalle discrète autorisée dans la déclaration d'un type de tableau formel générique (contraint) est une marque de type.

La partie discriminante d'un type privé formel générique ne doit pas inclure d'expression par défaut pour un discriminant. (Par conséquent, une variable déclarée par une déclaration d'objet doit être contrainte si son type est un type formel générique avec des discriminants.)

Dans la déclaration et le corps d'une unité générique, les opérations disponibles pour les valeurs d'un type formel générique (en dehors de toute opération supplémentaire spécifiée par un sous-programme formel générique) sont déterminées par la déclaration de paramètre générique pour le type formel :

  1. Pour une déclaration de type privé (en particulier, l'affectation, l'égalité et l'inégalité sont disponibles pour un type privé à moins qu'il ne soit limité).
  2. Pour une définition de type tableau (par exemple, elles incluent la formation de composants indexés et de tranches).
  3. Pour une définition de type accès (par exemple, des allocateurs peuvent être utilisés).

Les quatre formes de définition de type générique dans lesquelles une boîte apparaît (c'est-à-dire le délimiteur composé <>) correspondent aux principales formes suivantes de type scalaire :

  1. Types discrets : (<>) Les opérations disponibles sont les opérations communes aux types énumération et entier.
  2. Types entiers : intervalle <> : Les opérations disponibles sont les opérations des types entiers.
  3. Types à virgule flottante : chiffres <> : Les opérations disponibles sont celles de types réels.
  4. Types à virgule fixe : delta <> : Les opérations disponibles sont celles définies réels sans exposant.

Dans tous les cas (a) à (f) ci-dessus, chaque opération implicitement associée à un type formel (c'est-à-dire autre qu'une opération spécifiée par un sous-programme formel) est implicitement déclarée à la place de la déclaration du type formel. Il en va de même pour un type formel à virgule fixe, à l'exception des opérateurs multiplicateurs fournissant un résultat de type universal-fixed, puisque ces opérateurs spéciaux sont déclarés dans le paquet STANDARD.

Pour une instanciation de l'unité générique, chacune de ces opérations est l'opération de base correspondante ou l'opérateur prédéfini du type actuel correspondant. Pour un opérateur, cette règle s'applique même si l'opérateur a été redéfini pour le type actuel ou pour un type parent du type actuel.

Exemples de types formels génériques :

  1. type ITEM                     is private;
  2. type BUFFER(LENGTH : NATURAL) is limited private:
  3.  
  4. type ENUM                     is (<>);
  5. type INT                      is range <>;
  6. type ANGLE                    is delta <>;
  7. type MASS                     is digits <>;
  8.  
  9. type TABLE                    is array (ENUM) of ITEM;

Exemple d'une partie formelle générique déclarant un type entier formel :

  1. generic
  2.   type RANK is range <>;
  3.   FIRST  : RANK := RANK'FIRST;
  4.   SECOND : RANK := FIRST + 1;   -- l'opérateur "+" de type RANK

Sous-programmes formels génériques

Une déclaration de paramètre générique incluant une spécification de sous-programme déclare un sous-programme formel générique.

Deux formes alternatives de valeurs par défaut peuvent être spécifiées dans la déclaration d'un sous-programme formel générique. Dans ces formes, la spécification du sous-programme est suivie du mot réservé is et soit d'une boîte, soit du nom d'un sous-programme ou d'une entrée.

Un sous-programme formel générique désigne le sous-programme, le littéral d'énumération ou l'entrée fourni comme paramètre réel générique correspondant dans une instanciation générique.

Exemples de sous-programmes formels génériques :

  1. with function INCREASED : INTEGER) return INTEGER;
  2. with function SUM(X, Y : ITEM) return ITEM;
  3. with function "+"(X, Y : ITEM) return ITEM is <>;
  4. with function IMAGE(X : ENUM) return STRING is ENUM'IMAGE;
  5. with procedure UPDATE is DEFAULT_UPDATE;

Remarques : Les contraintes qui s'appliquent à un paramètre d'un sous-programme formel sont celles du paramètre correspondant dans la spécification du sous-programme réel correspondant (et non celles impliquées par la marque de type correspondante dans la spécification du sous-programme formel). Une remarque similaire s'applique au résultat d'une fonction. Dans la mesure du possible (pour éviter toute confusion), il est recommandé d'utiliser le nom d'un type de base plutôt que le nom d'un sous-type dans toute déclaration d'un sous-programme formel. Si, toutefois, le type de base est anonyme, il est recommandé d'utiliser le nom du sous-type défini par la déclaration de type.

Le type spécifié pour un paramètre formel d'un sous-programme formel générique peut être n'importe quel type visible, y compris un type formel générique de la même partie formelle générique.

Corps génériques

Le corps d'un sous-programme générique ou d'un paquet générique est un modèle pour les corps des sous-programmes ou paquets correspondants obtenus par des instanciations génériques. La syntaxe d'un corps générique est identique à celle d'un corps générique.

Pour chaque déclaration d'un sous-programme générique, il doit y avoir un corps correspondant.

L'élaboration d'un corps générique n'a d'autre effet que d'établir que ce corps peut désormais être utilisé comme modèle pour l'obtention des instances correspondantes.

Exemple de corps de procédure générique :

  1. procedure EXCHANGE(U, V : in out ELEM) is 
  2.   T : ELEM;                                          -- le type formel générique
  3. begin
  4.   T := U;
  5.   U := V;
  6.   V := T;
  7. end EXCHANGE;

Exemple de corps de fonction générique :

  1. function SQUARING(X : ITEM) return ITEM is
  2. begin
  3.   return X*X;                                        -- l'opérateur formel
  4. end;

Exemple de corps de paquet générique :

  1. package body ON_VECTORS is 
  2.  
  3.   function SUM(A, B : VECTOR) return VECTOR is
  4.     RESULT : VECTOR(A'RANGE);                        -- le type formel VECTOR
  5.     BIAS   : constant INTEGER := B'FIRST - A'FIRST;
  6.   begin
  7.     if A'LENGTH /= B'LENGTH then
  8.       raise LENGTH_ERROR;
  9.     end if;
  10.     for N in A'RANGE loop
  11.       RESULT(N) := SUM(A(N), B(N + BIAS));           -- la fonction formelle SUM
  12.     end loop;
  13.     return RESULT;
  14.   end;
  15.  
  16.   function SIGMA(A : VECTOR) return ITEM is
  17.     TOTAL : ITEM := A(A'FIRST);                      -- le type formel ITEM
  18.   begin
  19.     for N in A'FIRST + 1 .. A'LAST loop
  20.       TOTAL := SUM(TOTAL, A(N));                     -- la fonction formelle SUM
  21.     end loop;
  22.     return TOTAL;
  23.   end;
  24. end;

Instanciation générique

Une instance d'une unité générique est déclarée par une instanciation générique :

instantiation_generique ::=
  package identifiant is
      new nom_du_paquet_generique [piece_generique_actuel];
   | procedure identifier is
      new nom_de_procedure_generique [piece_generique_actuel];
   | function designator is
      new nom_de_fonction_generique [piece_generique_actuel];

piece_generique_actuel ::=
  (association_generique {, association_generique|)

association_generique ::=
  [parametre_formel_generique =>] parametre_generique_actuel

parametre_formel_generique ::= parametre_simple_nom | operateur_symbole

parametre_generique_actuel ::= expression | nom_variable
  | nom_sous_programme | nom_entree | marque_type

Un paramètre générique actuel explicite doit être fourni pour chaque paramètre formel générique, à moins que la déclaration de paramètre générique correspondante ne spécifie qu'une valeur par défaut peut être utilisée. Les associations génériques peuvent être positionnelles ou nommées, de la même manière que les associations de paramètres des appels de sous-programmes. Si deux ou plusieurs sous-programmes formels ont le même désignateur, les associations nommées ne sont pas autorisées pour les paramètres génériques correspondants.

Chaque paramètre générique actuel doit correspondre au paramètre formel générique correspondant. Une expression peut correspondre à un objet formel de mode in ; un nom de variable peut correspondre à un objet formel de mode in out ; un nom de sous-programme ou un nom d'entrée peut correspondre à un sous-programme formel ; une marque de type peut correspondre à un type formel.

L'instance est une copie de l'unité générique, à l'exception de la partie formelle générique ; ainsi, l'instance d'un paquet générique est un paquet, celle d'une procédure générique est une procédure et celle d'une fonction générique est une fonction. Pour chaque occurrence, au sein de l'unité générique, d'un nom désignant une entité donnée, la liste suivante définit quelle entité est désignée par l'occurrence correspondante au sein de l'instance.

  1. Pour un nom désignant l'unité générique : L'occurrence correspondante désigne l'instance.
  2. Pour un nom désignant un objet formel générique de mode in : Le nom correspondant désigne une constante dont la valeur est une copie de la valeur du paramètre générique actuel associé.
  3. Pour un nom désignant un objet formel générique de mode in out ; Le nom correspondant désigne la variable nommée par le paramètre générique actuel associé.
  4. Pour un nom désignant un type formel générique : Le nom correspondant désigne le sous-type nommé par le paramètre générique actuel associé (le sous-type actuel).
  5. Pour un nom désignant un discriminant d'un type formel générique : Le nom correspondant désigne le discriminant correspondant (il doit y en avoir un) du type actuel associé au type formel générique.
  6. Pour un nom désignant un sous-programme formel générique : le nom correspondant désigne le sous-programme, le littéral d'énumération ou l'entrée nommé par le paramètre actuel générique associé (le sous-programme actuel).
  7. Pour un nom désignant un paramètre formel d'un sous-programme formel générique : le nom correspondant désigne le paramètre formel correspondant du sous-programme actuel associé au sous-programme formel.
  8. Pour un nom désignant une entité locale déclarée dans l'unité générique : le nom correspondant désigne l'entité déclarée par la déclaration locale correspondante dans l'instance.
  9. Pour un nom désignant une entité globale déclarée en dehors de l'unité générique : le nom correspondant désigne la même entité globale.

Des règles similaires s'appliquent aux opérateurs et aux opérations de base : en particulier, les opérateurs formels suivent une règle similaire à la règle (f), les opérations locales suivent une règle similaire à la règle (h) et les opérations pour les types globaux suivent une règle similaire à la règle (i). De plus, si dans l'unité générique un opérateur prédéfini ou une opération de base d'un type formel est utilisé, alors dans l'instance l'occurrence correspondante fait référence à l'opération prédéfinie correspondante du type actuel associé au type formel. Les règles ci-dessus s'appliquent également à toute marque de type ou expression (par défaut) donnée dans la partie formelle générique de l'unité générique.

Pour l'élaboration d'une instanciation générique, chaque expression fournie comme paramètre actuel générique explicite est d'abord évaluée, ainsi que chaque expression apparaissant comme constituant d'un nom de variable ou d'un nom d'entrée fourni comme paramètre actuel générique explicite ; ces évaluations se déroulent dans un ordre n'étant pas défini par le langage. Ensuite, pour chaque association générique omise (le cas échéant), l'expression par défaut ou le nom par défaut correspondant est évalué; ces évaluations sont effectuées dans l'ordre des déclarations de paramètres génériques. Enfin, l'instance générée implicitement est élaborée. L'élaboration d'une instanciation générique peut également impliquer certaines vérifications de contraintes telles que décrites dans les sous-sections suivantes.

L'instanciation générique récursive n'est pas autorisée dans le sens suivant : si une unité générique donnée inclut une instanciation d'une seconde unité générique, alors l'instance générée par cette instanciation ne doit pas inclure une instance de la première unité générique (que cette instance soit générée directement, ou indirectement par des instanciations intermédiaires).

Exemples d'instanciations génériques :

  1. procedure SWAP is new EXCHANGE(ELEM => INTEGER);
  2. procedure SWAP is new EXCHANGE(CHARACTER);                                -- SWAP est surchargé
  3.  
  4. function SQUARE is new SQUARING (INTEGER);                                -- "*" de INTEGER utilisé par défaut
  5. function SQUARE is new SQUARING (ITEM => MATRIX, "*" => MATRIX_PRODUCT);
  6. function SQUARE is new SQUARING (MATRIX, MATRIX_PRODUCT);                 -- même que le précédent
  7.  
  8. package INT_VECTORS is new ON_VECTORS(INTEGER, TABLE, " + ");

Exemples d'utilisation des unités instanciées :

  1. SWAP(A, B);
  2. A := SQUARE(A);
  3.  
  4. T : TABLE(1 .. 5) := (10, 20, 30, 40, 50);
  5. N : INTEGER := INT_VECTORS.SIGMA(T);       -- 150
  6.  
  7. use INT_VECTORS;
  8. M : INTEGER := SIGMA(T);                   -- 150

Remarques : l'omission d'un paramètre générique actuel n'est autorisée que s'il existe une valeur par défaut correspondante. Si des expressions par défaut ou des noms par défaut (autres que des noms simples) sont utilisés, ils sont évalués dans l'ordre dans lequel les paramètres formels génériques correspondants sont déclarés.

Si deux sous-programmes surchargés déclarés dans une spécification de paquet générique ne diffèrent que par le type (formel) de leurs paramètres et de leurs résultats, il existe alors des instanciations légales pour lesquelles tous les appels de ces sous-programmes depuis l'extérieur de l'instance sont ambigus. Par exemple :

  1. generic
  2.   type A is (<>);
  3.   type B is private;
  4. package G is
  5.   function NEXT(X : A) return A;
  6.   function NEXT(X : B) return B;
  7. end;
  8.  
  9. package P is new G(A => BOOLEAN, B => BOOLEAN);
  10. -- les appels de P.NEXT sont ambigus

Règles de correspondance pour les objets formels

Un paramètre formel générique de mode in d'un type donné est mis en correspondance par une expression du même type. Si une unité générique possède un objet formel générique de mode in, une vérification est effectuée pour s'assurer que la valeur de l'expression appartient au sous-type désigné par la marque de type, comme pour une déclaration de constante explicite. L'exception CONSTRAINT_ERROR est levée si cette vérification échoue.

Un paramètre formel générique de mode in out d'un type donné est mis en correspondance par le nom d'une variable du même type. La variable ne doit pas être un paramètre formel de mode out ou une sous-composante de celui-ci. Le nom doit désigner une variable pour laquelle le renommage est autorisé.

Remarques : Le type d'un paramètre formel générique de mode in ne doit pas être un type limité. Les contraintes s'appliquant à un paramètre formel générique de mode in out sont celles du paramètre formel générique correspondant.

Règles de correspondance pour les types privés formels

Un type privé formel générique est mis en correspondance par tout type ou sous-type (le sous-type actuel) satisfaisant les conditions suivantes :

De plus, considérez toute occurrence du nom du type formel à un endroit où ce nom est utilisé comme indication de sous-type sans contrainte. Le sous-type réel ne doit pas être un type de tableau sans contrainte ou un type sans contrainte avec discriminants, si l'une de ces occurrences se trouve à un endroit où une contrainte ou des discriminants par défaut seraient requis pour un type de tableau ou pour un type avec discriminants. La même restriction s'applique aux occurrences du nom d'un sous-type du type formel, et aux occurrences du nom de tout type ou sous-type dérivé, directement ou indirectement, du type formel.

Si une unité générique a un type privé formel avec discriminants, l'élaboration d'une instanciation générique correspondante vérifie que le sous-type de chaque discriminant du type réel est le même que le sous-type du discriminant correspondant du type formel. L'exception CONSTRAINT_ERROR est levée si cette vérification échoue.

Règles de correspondance pour les types scalaires formels

Un type formel générique défini par (<>) correspond à tout sous-type discret (c'est-à-dire tout sous-type d'énumération ou d'entier). Un type formel générique défini par range <> correspond à tout sous-type d'entier. Un type formel générique défini par digits <> correspond à tout sous-type à virgule flottante. Un type formel générique défini par delta <> correspond à tout sous-type à virgule fixe. Aucune autre correspondance n'est possible pour ces types formels génériques.

Règles de correspondance pour les types de tableau formels

Un type de tableau formel est mis en correspondance par un sous-type de tableau actuel satisfaisant aux conditions suivantes :

Si une unité générique possède un type de tableau formel, l'élaboration d'une instanciation correspondante vérifie que les contraintes (le cas échéant) sur le type de composante sont les mêmes pour le type de tableau actuel que pour le type de tableau formel, et de même que pour toute position d'index donnée, les sous-types d'index ou les plages discrètes ont les mêmes limites. L'exception CONSTRAINT_ERROR est levée si cette vérification échoue.

Exemple :

  1. -- Étant donné le paquet générique
  2.  
  3. generic
  4.   type ITEM   is private;
  5.   type INDEX  is (<>);
  6.   type VECTOR is array (INDEX range <>) of ITEM;
  7.   type TABLE  is array (INDEX) of ITEM;
  8. package P is
  9.    ...
  10. end;
  11.  
  12. -- et les types
  13.  
  14. type MIX    is array (COLOR range <>) of BOOLEAN;
  15. type OPTION is array (COLOR) of BOOLEAN;
  16.  
  17. -- alors MIX peut correspondre à VECTOR et OPTION peut correspondre à TABLE
  18.  
  19. package R is new P(ITEM => BOOLEAN, INDEX => COLOR,
  20.                    VECTOR => MIX, TABLE => OPTION);
  21.  
  22. -- Notez que MIX ne peut pas correspondre à TABLE et OPTION ne peut pas correspondre à VECTOR

Remarque : pour les règles ci-dessus, si l'un des types d'index ou de composant du type de tableau formel est lui-même un type formel, alors dans l'instance, son nom désigne le sous-type actuel correspondant.

Règles de correspondance pour les types d'accès formels

Un type d'accès formel est mis en correspondance avec un sous-type d'accès réel si le type des objets désignés est le même pour le type actuel que pour le type formel. Si le type désigné n'est pas un type scalaire, les sous-types désignés doivent être tous deux contraints ou tous deux non contraints.

Si une unité générique possède un type d'accès formel, l'élaboration d'une instanciation correspondante vérifie que les contraintes sur les objets désignés sont les mêmes pour le sous-type d'accès réel que pour le type d'accès formel. L'exception CONSTRAINT_ERROR est levée si cette vérification échoue.

Exemple :

  1. -- les types formels du paquet générique
  2. generic
  3.   type NODE is private;
  4.   type LINK is access NODE;
  5. package P is
  6.   ...
  7. end;
  8.  
  9. -- peut être associé aux types actuels
  10.  
  11. type CAR;
  12. type CAR_NAME is access CAR;
  13.  
  14. type CAR is
  15.   record
  16.     PRED, SUCC : CAR_NAME;
  17.     NUMBER     : LICENSE_NUMBER;
  18.     OWNER      : PERSON;
  19.   end record;
  20.   
  21. -- dans l'instanciation générique suivante
  22.  
  23. package R is new P(NODE => CAR, LINK => CAR_NAME);

Remarque : pour les règles ci-dessus, si le type désigné est lui-même un type formel, alors dans l'instance, son nom désigne le sous-type actuel correspondant.

Règles de correspondance pour les sous-programmes formels

Un sous-programme formel est mis en correspondance par un sous-programme réel, un littéral d'énumération ou une entrée si les deux ont le même profil de paramètre et de type de résultat; de plus, les modes de paramètre doivent être identiques pour les paramètres formels se trouvant à la même position de paramètre.

Si une unité générique a un sous-programme par défaut spécifié par un nom, ce nom doit désigner un sous-programme, un littéral d'énumération ou une entrée correspondant au sous-programme formel (au sens ci-dessus). L'évaluation du nom par défaut a lieu lors de l'élaboration de chaque instanciation utilisant la valeur par défaut.

Si une unité générique a un sous-programme par défaut spécifié par une boîte, le paramètre réel correspondant peut être omis si un sous-programme, un littéral d'énumération ou une entrée correspondant au sous-programme formel et avec le même désignateur que le sous-programme formel est directement visible à l'endroit de l'instanciation générique ; ce sous-programme, littéral d'énumération ou entrée est alors utilisé par défaut (il doit y avoir exactement un sous-programme, littéral d'énumération ou entrée satisfaisant les conditions précédentes).

Exemple :

  1. -- étant donné la spécification de fonction générique
  2.  
  3. generic
  4.   type ITEM is private;
  5.   with function "*" (U, V : ITEM) return ITEM is <>;
  6. function SQUARING(X : ITEM) return ITEM;
  7.  
  8. -- et la fonction
  9.  
  10. function MATRIX_PRODUCT(A, B : MATRIX) return MATRIX;
  11.  
  12. -- l'instanciation suivante est possible
  13.  
  14. function SQUARE is new SQUARING(MATRIX, MATRIX_PRODUCT);
  15.  
  16. -- les instanciations suivantes sont équivalentes
  17.  
  18. function SQUARE is new SQUARING(ITEM => INTEGER, "*" => "*");
  19. function SQUARE is new SQUARING(INTEGER, "*");
  20. function SQUARE is new SQUARING(INTEGER);

Remarques : Les règles de correspondance pour les sous-programmes formels énoncent des exigences similaires à celles s'appliquant aux déclarations de renommage de sous-programmes. En particulier, le nom d'un paramètre du sous-programme formel n'a pas besoin d'être identique à celui du paramètre correspondant du sous-programme actuel; de même, pour ces paramètres, les expressions par défaut n'ont pas besoin de correspondre.

Un sous-programme formel est mis en correspondance par un attribut d'un type si l'attribut est une fonction avec une spécification correspondante. Un littéral d'énumération d'un type donné correspond à une fonction formelle sans paramètre dont le type de résultat est le type donné.

Exemple de paquet générique

L'exemple suivant fournit une formulation possible de piles au moyen d'un paquet générique. La taille de chaque pile et le type des éléments de la pile sont fournis comme paramètres génériques.

  1. generic
  2.   SIZE : POSITIVE;
  3.   type ITEM is private;
  4. package STACK is
  5.   procedure PUSH (E : in ITEM);
  6.   procedure POP (E : out ITEM);
  7.   OVERFLOW, UNDERFLOW : exception;
  8. end STACK;
  9.  
  10. package body STACK is
  11.  
  12.   type TABLE is array (POSITIVE range <>) of ITEM;
  13.   SPACE : TABLEO .. SIZE);
  14.   INDEX : NATURAL := 0;
  15.   
  16.   procedure PUSH(E : in ITEM) is
  17.   begin
  18.     if INDEX >= SIZE then
  19.       raise OVERFLOW;
  20.     end if;
  21.     INDEX := INDEX + 1;
  22.     SPACE(INDEX) := E;
  23.   end PUSH;
  24.   
  25.   procedure POP(E : out ITEM) is
  26.   begin
  27.     if INDEX = 0 then
  28.        raise UNDERFLOW;
  29.     end if;
  30.     E := SPACE(INDEX);
  31.     INDEX := INDEX - 1;
  32.   end POP;
  33. end STACK;

Des instances de ce paquet générique peuvent être obtenues comme suit :

  1. package STACK_INT is new STACK(SIZE => 200, ITEM => INTEGER);
  2. package STACK_BOOL is new STACK(100, BOOLEAN);

Par la suite, les procédures des paquets instanciés peuvent être appelées comme suit :

  1. STACK_INT.PUSH(N);
  2. STACK_BOOL.PUSH(TRUE);

Alternativement, une formulation générique du type STACK peut être donnée comme suit (corps du paquet omis) :

  1. generic
  2.   type ITEM is private;
  3. package ON_STACKS is
  4.   type STACK(SIZE : POSITIVE) is limited private:
  5.   procedure PUSH (S : in out STACK; E : in  ITEM);
  6.   procedure POP  (S : in out STACK; E : out ITEM);
  7.   OVERFLOW, UNDERFLOW : exception;
  8. private
  9.   type TABLE is array (POSITIVE range <>) of ITEM;
  10.   type STACK(SIZE : POSITIVE) is
  11.   record
  12.     SPACE : TABLE(1 .. SIZE);
  13.     INDEX : NATURAL := 0;
  14.   end record;
  15. end;

Pour utiliser un tel paquet, une instanciation doit être créée et ensuite des piles du type correspondant peuvent être déclarées :

  1. declare
  2.   package STACK_REAL is new ON_STACKS(REAL); use STACK_REAL;
  3.   S : STACK(100);
  4. begin
  5.     ...
  6.   PUSH(S, 2.54);
  7.     ...
  8. end;


PARTAGER CETTE PAGE SUR
Dernière mise à jour : Mardi, le 7 janvier 2025