Les sous-programmes
Les sous-programmes sont l'une des quatre formes d'unités de programme dont les programmes peuvent être composés. Les autres formes sont les paquets, les unités de tâches et les unités génériques.
Un sous-programme est une unité de programme dont l'exécution est appelée par un appel de sous-programme. Il existe deux formes de sous-programme : les procédures et les fonctions. Un appel de procédure est une instruction; un appel de fonction est une expression et renvoie une valeur. La définition d'un sous-programme peut être donnée en deux parties : une déclaration de sous-programme définissant ses conventions d'appel et un corps de sous-programme définissant son exécution.
Déclarations de sous-programme
Une déclaration de sous-programme déclare une procédure ou une fonction, comme indiqué par le mot réservé initial :
declaration_sous_programme ::= specification_du_sous_programme; specification_du_sous_programme ::= procedure identifiant [partie_formelle] | function designateur [partie_formelle] return marque_type designateur ::= identifiant | operateur_symbole operateur_symbole ::= chaine_litterale partie_formelle ::= (parametre_specification {; parametre_specification}) parametre_specification ::= liste_identifiant : mode marque_type [:= expression] mode ::= [in] | in out | out |
La spécification d'une procédure spécifie son identifiant et ses paramètres de format (le cas échéant). La spécification d'une fonction spécifie son désignateur, ses paramètres formels (le cas échéant) et le sous-type de la valeur renvoyée (le sous-type de résultat). Un désignateur étant un symbole d'opérateur est utilisé pour la surcharge d'un opérateur. La séquence de caractères représentée par un symbole d'opérateur doit être un opérateur appartenant à l'une des six classes d'opérateurs surchargés (les espaces supplémentaires ne sont pas autorisés et la casse des lettres n'est pas significative).
Une spécification de paramètre avec plusieurs identifiants est équivalente à une séquence de spécifications de paramètres simples. Chaque spécification de paramètre simple déclare un paramètre formel. Si aucun mode n'est explicitement donné, le mode in est supposé. Si une spécification de paramètre se termine par une expression, l'expression est l'expression par défaut du paramètre formel. Une expression par défaut n'est autorisée dans une spécification de paramètre 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 correspondant.
L'utilisation d'un nom désignant un paramètre formel n'est pas autorisée dans les expressions par défaut d'une partie formelle si la spécification du paramètre est elle-même donnée dans cette partie formelle. L'élaboration d'une déclaration de sous-programme élabore la partie formelle correspondante. L'élaboration d'une partie formelle n'a aucun autre effet.
Exemples de déclarations de sous-programme :
- procedure TRAVERSE_TREE;
- procedure INCREMENTS : in out INTEGER);
- procedure RIGHT_INDENT(MARGIN : out LINE_SIZE);
- procedure SWITCH(FROM, TO : in out LINK);
-
- function RANDOM return PROBABILITY;
-
- function MIN_CELL(X : LINK) return CELL;
- function NEXT_FRAME(K : POSITIVE) return FRAME;
- function DOT_PRODUCT(LEFT,RIGHT: VECTOR) return REAL;
- function "*"(LEFT,RIGHT : MATRIX) return MATRIX;
Exemples de paramètres avec des expressions par défaut :
Remarques : L'évaluation des expressions par défaut est provoquée par certains appels de sous-programmes (les expressions par défaut ne sont pas évaluées lors de l'élaboration de la déclaration de sous-programme).
Tous les sous-programmes peuvent être appelés de manière récursive et sont réentrants.
Modes de paramètres formels
On dit que la valeur d'un objet est lue lorsque cette valeur est évaluée; on dit aussi qu'elle est lue lorsque l'un de ses sous-composantes est lu. On dit que la valeur d'une variable est mise à jour lorsqu'une affectation est effectuée sur la variable, et aussi (indirectement) lorsque la variable est utilisée comme paramètre actuel d'un appel de sous-programme ou d'une instruction d'appel d'entrée qui met à jour sa valeur; on dit aussi qu'elle est mise à jour lorsque l'un de ses sous-composantes est mis à jour.
Un paramètre formel d'un sous-programme possède l'un des trois modes suivants :
Mode | Description | |
---|---|---|
in | Le paramètre formel est une constante et permet uniquement la lecture de la valeur du paramètre actuel associé. | |
in out | Le paramètre formel est une variable et permet à la fois la lecture et la mise à jour de la valeur du paramètre actuel associé. | |
out | Le paramètre formel est une variable et permet de mettre à jour la valeur du paramètre actuel associé. La valeur d'un paramètre scalaire qui n'est pas mise à jour par l'appel est indéfinie au retour ; il en va de même pour la valeur d'un sous-composant scalaire, autre qu'un discriminant. La lecture des bornes et des discriminants du paramètre formel et de ses sous-composants est autorisée, mais aucune autre lecture n'est autorisée. |
Pour un paramètre scalaire, les effets ci-dessus sont obtenus par copie : au début de chaque appel, si le mode est in ou in out, la valeur du paramètre actuel est copiée dans le paramètre formel associé ; puis après l'achèvement normal du corps du sous-programme, si le mode est in out ou out, la valeur du paramètre formel est recopiée dans le paramètre actuel associé. Pour un paramètre dont le type est un type d'accès, la copie en entrée est utilisée pour les trois modes, et la copie en retour pour les modes in out et out.
Pour un paramètre dont le type est un tableau, un enregistrement ou une tâche, une implémentation peut également obtenir les effets ci-dessus par copie, comme pour les types scalaires. De plus, si la copie est utilisée pour un paramètre de mode out, alors la copie en entrée est requise au moins pour les limites et les discriminants du paramètre actuel et de ses sous-composants, ainsi que pour chaque sous-composante dont le type est un type d'accès. Alternativement, une implémentation peut obtenir ces effets par référence, c'est-à-dire en faisant en sorte que chaque utilisation du paramètre formel (pour lire ou mettre à jour sa valeur) soit traitée comme une utilisation du paramètre actuel associé, tout au long de l'exécution de l'appel du sous-programme. Le langage ne définit pas lequel de ces deux mécanismes doit être adopté pour le passage de paramètres, ni si différents appels au même sous-programme doivent utiliser le même mécanisme. L'exécution d'un programme est erronée si son effet dépend du mécanisme sélectionné par l'implémentation. Pour un paramètre dont le type est un type privé, les effets ci-dessus sont obtenus selon la règle s'appliquant à la déclaration de type complète correspondante.
Dans le corps d'un sous-programme, un paramètre formel est soumis à toute contrainte résultant de la marque de type donnée dans sa spécification de paramètre. Pour un paramètre formel d'un type de tableau non contraint, les limites sont obtenues à partir du paramètre actuel, et le paramètre formel est contraint par ces limites. Pour un paramètre formel dont la déclaration spécifie un type non contraint (privé ou enregistrement) avec des discriminants, les discriminants du paramètre formel sont initialisés avec les valeurs des discriminants correspondants du paramètre actuel; le paramètre formel est non contraint si et seulement si le mode est in out ou out et le nom de variable donné pour le paramètre actuel désigne une variable non contrainte.
Si le paramètre actuel d'un appel de sous-programme est un sous-composante dépendant des discriminants d'une variable d'enregistrement non contrainte, alors l'exécution de l'appel est erronée si la valeur de l'un des discriminants de la variable est modifiée par cette exécution; cette règle ne s'applique pas si le mode est in et que le type du sous-composante est un type scalaire ou un type d'accès.
Pour les paramètres de type tableau et enregistrement, les règles de passage de paramètres ont les conséquences suivantes :
- Si l'exécution d'un sous-programme est abandonnée suite à une exception, la valeur finale d'un paramètre actuel d'un tel type peut être soit sa valeur avant l'appel, soit une valeur affectée au paramètre formel pendant l'exécution du sous-programme.
- Si aucun paramètre actuel d'un tel type n'est accessible par plus d'un chemin, alors l'effet d'un appel de sous-programme (sauf abandon) est le même, que l'implémentation utilise ou non la copie pour le passage de paramètres. Cependant, s'il existe plusieurs chemins d'accès à un tel paramètre (par exemple, si une variable globale ou un autre paramètre formel fait référence au même paramètre actuel), alors la valeur du paramètre formel est indéfinie après la mise à jour du paramètre actuel autrement que par la mise à jour du paramètre formel. Un programme utilisant une telle valeur indéfinie est erroné.
Les mêmes modes de paramètres sont définis pour les paramètres formels des entrées avec la même signification que pour les sous-programmes. Des modes de paramètres différents sont définis pour les paramètres formels génériques.
Pour tous les modes, si un paramètre actuel désigne une tâche, le paramètre formel associé désigne la même tâche; il en va de même pour une sous-composante d'un paramètre actuel et le sous-composant correspondant du paramètre formel associé.
Corps de sous-programme
Un corps de sous-programme spécifie l'exécution d'un sous-programme :
sous_programme_corps ::= specification_du_sous_programme is [ partie_declarative] begin sequence_d_instructions [ exception gestionnaire_d_exceptions | gestionnaire_d_exceptions|] end [designateur]; |
La déclaration d'un sous-programme est facultative. En l'absence d'une telle déclaration, la spécification du sous-programme du corps du sous-programme (ou du corps du sous-programme) fait office de déclaration. Pour chaque déclaration de sous-programme, il doit y avoir un corps correspondant (sauf pour un sous-programme écrit dans un autre langage). Si une déclaration et un corps sont tous deux fournis, la spécification du sous-programme du corps doit être conforme à la spécification du sous-programme de la déclaration.
Si un désignateur apparaît à la fin d'un corps de sous-programme, il doit répéter le désignateur de la spécification du sous-programme.
L'élaboration d'un corps de sous-programme n'a d'autre effet que d'établir que le corps peut désormais être utilisé pour l'exécution des appels du sous-programme.
L'exécution d'un corps de sous-programme est appelée par un appel de sous-programme. Pour cette exécution, après avoir établi l'association entre les paramètres formels et les paramètres actuels, la partie déclarative du corps est élaborée, et la séquence d'instructions du corps est ensuite exécutée. Une fois le corps terminé, un retour est effectué vers l'appelant (et toute copie nécessaire des paramètres formels vers les paramètres actuels se produit). Les gestionnaires d'exceptions facultatifs à la fin d'un corps de sous-programme gèrent les exceptions levées pendant l'exécution de la séquence d'instructions du corps du sous-programme.
Remarque : il résulte des règles de visibilité que si un sous-programme déclaré dans un paquet doit être visible en dehors du paquet, une spécification de sous-programme doit être donnée dans la partie visible du paquet. Les mêmes règles imposent qu'une déclaration de sous-programme soit donnée si un appel du sous-programme se produit textuellement avant le corps du sous-programme (la déclaration doit alors se produire avant l'appel dans le texte du programme). Une déclaration de sous-programme et le corps correspondant doivent tous deux se produire immédiatement dans la même région déclarative.
Exemple de corps de sous-programme :
Règles de conformité
Chaque fois que les règles de langage exigent ou autorisent la spécification d'un sous-programme donné à plusieurs endroits, les variations suivantes sont autorisées à chaque endroit :
- Un littéral numérique peut être remplacé par un littéral numérique différent si et seulement si les deux ont la même valeur.
- Un nom simple peut être remplacé par un nom développé dans lequel ce nom simple est le sélecteur, si et seulement si aux deux endroits la signification du nom simple est donnée par la même déclaration.
- Un littéral de chaîne donné comme symbole d'opérateur peut être remplacé par un littéral de chaîne différent si et seulement si les deux représentent le même opérateur.
Deux spécifications de sous-programme sont dites conformes si, hormis les commentaires et les variations autorisées ci-dessus, les deux spécifications sont formées par la même séquence d'éléments lexicaux, et les éléments lexicaux correspondants ont la même signification selon les règles de visibilité et de surcharge. La conformité est également définie pour les parties formelles, les parties discriminantes et les marques de type (pour les constantes différées et pour les paramètres actuels ayant la forme d'une conversion de type).
Remarques : Un nom simple peut être remplacé par un nom développé même si le nom simple est lui-même le préfixe d'un composant sélectionné. Par exemple, Q.R peut être remplacé par P.Q.R si Q est déclaré immédiatement dans P.
Les spécifications suivantes ne sont pas conformes car elles ne sont pas formées par la même séquence d'éléments lexicaux :
Extension en ligne des sous-programmes
Le pragma INLINE est utilisé pour indiquer que l'extension en ligne du corps du sous-programme est souhaitée pour chaque appel de chacun des sous-programmes nommés. La forme de ce pragma est la suivante :
pragma INLINE (nom [, nom]); |
Chaque nom est soit le nom d'un sous-programme, soit le nom d'un sous-programme générique. Le pragma INLINE n'est autorisé qu'à la place d'un élément déclaratif dans une partie déclarative ou une spécification de paquet, ou après une unité de bibliothèque dans une compilation, mais avant toute unité de compilation ultérieure.
Si le pragma apparaît à la place d'un élément déclaratif, chaque nom doit désigner un sous-programme ou un sous-programme générique déclaré par un élément déclaratif antérieur de la même partie déclarative ou de la même spécification de paquet. Si plusieurs sous-programmes (surchargés) satisfont à cette exigence, le pragma s'applique à tous. Si le pragma apparaît après une unité de bibliothèque donnée, le seul nom autorisé est le nom de cette unité. Si le nom d'un sous-programme générique est mentionné dans le pragma, cela indique que l'expansion en ligne est souhaitée pour les appels de tous les sous-programmes obtenus par instanciation de l'unité générique nommée.
La signification d'un sous-programme n'est pas modifiée par le pragma INLINE. Pour chaque appel des sous-programmes nommés, une implémentation est libre de suivre ou d'ignorer la recommandation exprimée par le pragma. (Notez, en particulier, que la recommandation ne peut généralement pas être suivie pour un sous-programme récursif.)
Appels de sous-programme
Un appel de sous-programme est soit une instruction d'appel de procédure, soit un appel de fonction; il appel l'exécution du corps du sous-programme correspondant. L'appel spécifie l'association des paramètres actuels, le cas échéant, avec les paramètres formels du sous-programme :
instruction_d_appel_de_procedure ::= nom_procedure [partie_parametre_actuel]; appel_fonction ::= nom_fonction [partie_parametre_actuel] partie_parametre_actuel ::= (association_parametre (, association_parametre|) association_parametre ::= [ parametre_formel =>] parametre_actuel parametre_formel ::= parametre_simple_name parametre_actuel ::= expression | nom_variable | marque_type(nom_variable) |
Chaque association de paramètres associe un paramètre actuel à un paramètre formel correspondant. Une association de paramètres est dite nommée si le paramètre formel est nommé explicitement ; sinon, elle est dite positionnelle. Pour une association positionnelle, le paramètre actuel correspond au paramètre formel ayant la même position dans la partie formelle.
Les associations nommées peuvent être données dans n'importe quel ordre, mais si des associations positionnelles et nommées sont utilisées dans le même appel, les associations positionnelles doivent apparaître en premier, à leur position normale. Ainsi, une fois qu'une association nommée est utilisée, le reste de l'appel doit utiliser uniquement des associations nommées.
Pour chaque paramètre formel d'un sous-programme, un appel de sous-programme doit spécifier exactement un paramètre actuel correspondant. Ce paramètre actuel est spécifié soit explicitement, par une association de paramètres, soit, en l'absence d'une telle association, par une expression par défaut.
Les associations de paramètres d'un appel de sous-programme sont évaluées dans un ordre n'étant pas défini par le langage. De même, les règles du langage ne définissent pas dans quel ordre les valeurs des paramètres in out ou out sont recopiées dans les paramètres actuels correspondants (lorsque cela est fait).
Exemples d'appels de procédure :
- TRAVERSE_TREE;
- TABLE_MANAGER.INSERT(E);
- PRINT_HEADER(128, TITLE, TRUE);
-
- SWITCH(FROM => X, TO => NEXT);
- PRINT_HEADER(128, HEADER => TITLE, CENTER => TRUE);
- PRINT_HEADER(HEADER => TITLE, CENTER => TRUE, PAGES => 128);
Exemples d'appels de fonctions :
- DOT_PRODUCT(U, V)
- CLOCK
Associations de paramètres
Chaque paramètre actuel doit avoir le même type que le paramètre formel correspondant.
Un paramètre actuel associé à un paramètre formel de mode in doit être une expression ; il est évalué avant l'appel.
Un paramètre actuel associé à un paramètre formel de mode in out ou out doit être soit le nom d'une variable, soit la forme d'une conversion de type dont le paramètre est le nom d'une variable. Dans les deux cas, pour le mode in out, la variable ne doit pas être un paramètre formel de mode out ou un sous-composante de celui-ci. Pour un paramètre actuel ayant la forme d'une conversion de type, la marque de type doit être conforme à la marque de type du paramètre formel; les types d'opérande et de cible autorisés sont les mêmes que pour les conversions de type.
Le nom de variable donné pour un paramètre actuel de mode in out ou out est évalué avant l'appel. Si le paramètre actuel a la forme d'une conversion de type, alors avant l'appel, pour un paramètre de mode in out, la variable est convertie dans le type spécifié ; après l'achèvement (normal) du corps du sous-programme, pour un paramètre de mode in out ou out, le paramètre formel est reconverti dans le type de la variable. (Le type spécifié dans la conversion doit être celui du paramètre formel.)
Les contrôles de contrainte suivants sont effectués pour les paramètres de type scalaire et d'accès :
- Avant l'appel : pour un paramètre de mode in ou in out, il est vérifié que la valeur du paramètre actuel appartient au sous-type du paramètre formel.
- Après l'achèvement (normal) du corps du sous-programme : pour un paramètre de mode in out ou out, il est vérifié que la valeur du paramètre formel appartient au sous-type de la variable actuelle. Dans le cas d'une conversion de type, la valeur du paramètre formel est reconvertie et le contrôle s'applique au résultat de la conversion.
Dans chacun des cas ci-dessus, l'exécution du programme est erronée si la valeur vérifiée est indéfinie.
Pour les autres types, pour tous les modes, une vérification est effectuée avant l'appel comme pour les types scalaires et d'accès; aucune vérification n'est effectuée au retour.
L'exception CONSTRAINT_ERROR est levée à l'endroit de l'appel du sous-programme si l'une de ces vérifications échoue.
Remarque : pour les types tableau et pour les types avec discriminants, la vérification avant l'appel est suffisante (une vérification au retour serait redondante) si la marque de type du paramètre formel désigne un sous-type contraint, car ni les limites du tableau ni les discriminants ne peuvent alors varier.
Si cette marque de type désigne un type de tableau sans contrainte, le paramètre formel est contraint par les 12 bornes du paramètre actuel correspondant et aucune vérification (ni avant l'appel ni au retour) n'est nécessaire. De même, aucune vérification n'est nécessaire si la marque de type désigne un type sans contrainte avec des discriminants, puisque le paramètre formel est alors contraint exactement comme le paramètre actuel correspondant.
Paramètres par défaut
Si une spécification de paramètre inclut une expression par défaut pour un paramètre de mode in, les appels de sous-programme correspondants n'ont pas besoin d'inclure une association de paramètres pour le paramètre. Si une association de paramètres est ainsi omise d'un appel, le reste de l'appel, après toute association positionnelle initiale, doit utiliser uniquement des associations nommées.
Pour toute association de paramètres omise, l'expression par défaut est évaluée avant l'appel et la valeur résultante est utilisée comme paramètre actuel implicite.
Exemples de procédures avec des valeurs par défaut :
Exemples de leurs appels :
- ACTIVATE(X);
- ACTIVATED, AFTER => Y);
- ACTIVATED, WAIT => 60.0, PRIOR => TRUE);
- ACTIVATED, Y, 10.0, FALSE);
-
- PAIR;
- PAIR(LEFT => new PERSON, RIGHT => new PERSON);
Remarque : si une expression par défaut est utilisée pour deux paramètres ou plus dans une spécification à paramètres multiples, l'expression par défaut est évaluée une fois pour chaque paramètre omis. Par conséquent, dans les exemples ci-dessus, les deux appels de PAIR sont équivalents.
Sous-programmes de fonction
Une fonction est un sous-programme renvoyant une valeur (le résultat de l'appel de fonction). La spécification d'une fonction commence par le mot réservé function, et les paramètres, s'il y en a, doivent avoir le mode in (que ce mode soit spécifié explicitement ou implicitement). Les instructions du corps de la fonction (à l'exclusion des instructions des unités de programme qui sont internes au corps de la fonction) doivent inclure une ou plusieurs instructions return spécifiant la valeur renvoyée.
L'exception PROGRAM_ERRGR est levée si un corps de fonction est quitté autrement que par une instruction return. Cela ne s'applique pas si l'exécution de la fonction est abandonnée à la suite d'une exception.
Exemple :
Profil de type de paramètre et de résultat - Surcharge de sous-programmes
On dit que deux parties formelles ont le même profil de type de paramètre si et seulement si elles ont le même nombre de paramètres, et à chaque position de paramètre les paramètres correspondants ont le même type de base. Un sous-programme ou une entrée a le même profil de type de paramètre et de résultat qu'un autre sous-programme ou une autre entrée si et seulement si les deux ont le même profil de type de paramètre, et soit les deux sont des fonctions avec le même type de base de résultat, soit aucun des deux n'est une fonction.
Le même identifiant de sous-programme ou symbole d'opérateur peut être utilisé dans plusieurs spécifications de sous-programme. L'identifiant ou le symbole d'opérateur est alors dit surchargé; les sous-programmes ayant cet identifiant ou symbole d'opérateur sont également dits surchargés et se surchargent mutuellement. Si deux sous-programmes se surchargent mutuellement, l'un d'eux ne peut masquer l'autre que si les deux sous-programmes ont le même profil de type de paramètre et de résultat.
Un appel à un sous-programme surchargé est ambigu (et donc illégal) si le nom du sous-programme, le nombre d'associations de paramètres, les types et l'ordre des paramètres actuels, les noms des paramètres formels (si des associations nommées sont utilisées) et le type de résultat (pour les fonctions) ne sont pas suffisants pour déterminer exactement une spécification de sous-programme (surchargé).
Exemples de sous-programmes surchargés :
Exemples d'appels :
- PUT(28);
- PUT("aucune ambiguïté possible ici");
-
- SET(TINT => RED);
- SET(SIGNAL => RED);
- SET(COLOR'(RED));
- -- SET (RED) serait ambigu puisque RED peut désigner une valeur de type COLOR ou de type LIGHT
Remarques : La notion de profil de type de paramètre et de résultat n'inclut pas les noms de paramètres, les modes de paramètres, les sous-types de paramètres, les expressions par défaut et leur présence ou absence.
Des ambiguïtés peuvent (mais ne sont pas obligatoires) survenir lorsque les paramètres actuels de l'appel d'un sous-programme surchargé sont eux-mêmes des appels de fonction surchargés, des littéraux ou des agrégats. Des ambiguïtés peuvent également (mais ne sont pas obligatoires) survenir lorsque plusieurs sous-programmes surchargés appartenant à différents paquets sont visibles. Ces ambiguïtés peuvent généralement être résolues de plusieurs manières : des expressions qualifiées peuvent être utilisées pour certains ou tous les paramètres actuels, et pour le résultat, le cas échéant ; le nom du sous-programme peut être exprimé plus explicitement sous la forme d'un nom développé; enfin, le sous-programme peut être renommé.
Surcharge des opérateurs
La déclaration d'une fonction dont le désignateur est un symbole d'opérateur est utilisée pour surcharger un opérateur. La séquence de caractères du symbole d'opérateur doit être un opérateur logique, relationnel, d'addition binaire, d'addition unaire, de multiplication ou de priorité la plus élevée. Ni les tests d'appartenance ni les formes de contrôle de court-circuit ne sont autorisés comme désignateurs de fonction.
La spécification de sous-programme d'un opérateur unaire doit avoir un seul paramètre. La spécification de sous-programme d'un opérateur binaire doit avoir deux paramètres; pour chaque utilisation de cet opérateur, le premier paramètre prend l'opérande gauche comme paramètre actuel, le deuxième paramètre prend l'opérande droit. De même, une instanciation de fonction générique dont le désignateur est un symbole d'opérateur n'est autorisée que si la spécification de la fonction générique a le nombre correspondant de paramètres. Les expressions par défaut ne sont pas autorisées pour les paramètres d'un opérateur (que l'opérateur soit déclaré avec une spécification de sous-programme explicite ou par une instanciation générique).
Pour chacun des opérateurs "+" et la surcharge est autorisée à la fois comme opérateur unaire et comme opérateur binaire.
La déclaration explicite d'une fonction qui surcharge l'opérateur d'égalité autrement que par une déclaration de renommage, n'est autorisée que si les deux paramètres sont du même type limité. Une surcharge d'égalité doit fournir un résultat du type prédéfini BOOLEAN; elle surcharge aussi implicitement l'opérateur d'inégalité "/=" de sorte que celui-ci donne toujours le résultat complémentaire à l'opérateur d'égalité. La surcharge explicite de l'opérateur d'inégalité n'est pas autorisée.
Une déclaration de renommage dont le désignateur est l'opérateur d'égalité n'est autorisée que pour renommer un autre opérateur d'égalité. (Par exemple, une telle déclaration de renommage peut être utilisée lorsque l'égalité est visible par sélection mais pas directement visible.)
Remarque : la surcharge d'opérateurs relationnels n'affecte pas les comparaisons de base telles que le test d'appartenance à un intervalle ou les choix dans une instruction case.
Exemples :