IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

[D2010] Comportement modifié pour le passage d'un packed record en paramètre constant ?


Sujet :

Langage Delphi

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut [D2010] Comportement modifié pour le passage d'un packed record en paramètre constant ?
    Bonjour,

    Je suis en train de regarder s'il est intéressant de passer à Delphi 2010, et j'essaie donc de recompiler mes applications sous cet environnement.

    J'ai un problème avec une fonction d'un très vieux composant que j'utilise toujours
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    procedure GammaCorrection(Gamma: Single; const Colors: array of TRGBQuad);
    const
      Inv255 = 1.0 / 255;
    var
      i: Integer;
      InvGamma: double;
    begin
      InvGamma := 1.0/Gamma;
      for i := Low(Colors) to High(Colors) do
        with Colors[i] do
        begin
          rgbRed	:= Round(255 * Power(rgbRed   * Inv255, InvGamma));
          rgbGreen	:= Round(255 * Power(rgbGreen * Inv255, InvGamma));
          rgbBlue	:= Round(255 * Power(rgbBlue  * Inv255, InvGamma));
        end;
    end;
    Ce code compile sous Delphi 7 et Delphi 2007, mais pas sous Delphi 2010, j'ai une erreur E2064 (left operand cannot be assigned) pour toutes les lignes où j'essaie de modifier les éléments du packed record.

    Est-ce une évolution du langage ? Un bug ? Autre ?

    Merci

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par sovitec Voir le message
    Bonjour,

    Je suis en train de regarder s'il est intéressant de passer à Delphi 2010, et j'essaie donc de recompiler mes applications sous cet environnement.

    J'ai un problème avec une fonction d'un très vieux composant que j'utilise toujours
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    procedure GammaCorrection(Gamma: Single; const Colors: array of TRGBQuad);
    const
      Inv255 = 1.0 / 255;
    var
      i: Integer;
      InvGamma: double;
    begin
      InvGamma := 1.0/Gamma;
      for i := Low(Colors) to High(Colors) do
        with Colors[i] do
        begin
          rgbRed	:= Round(255 * Power(rgbRed   * Inv255, InvGamma));
          rgbGreen	:= Round(255 * Power(rgbGreen * Inv255, InvGamma));
          rgbBlue	:= Round(255 * Power(rgbBlue  * Inv255, InvGamma));
        end;
    end;
    Ce code compile sous Delphi 7 et Delphi 2007, mais pas sous Delphi 2010, j'ai une erreur E2064 (left operand cannot be assigned) pour toutes les lignes où j'essaie de modifier les éléments du packed record.

    Est-ce une évolution du langage ? Un bug ? Autre ?

    Merci
    pourquoi Colors est-il déclaré en constante alors qu'il est modifié ?!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    type
      TColors = array of TRGBQuad;
    procedure GammaCorrection(Gamma: Single; var Colors: TColors);

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    pourquoi Colors est-il déclaré en constante alors qu'il est modifié ?!
    Alors ça je ne sais pas, c'est dans le source d'un composant tiers.

    La correction était simple, je me demandais juste s'il y avait eu une évolution dans le langage qui ferait que ce code ne compile plus.

  4. #4
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Bonjour,
    Citation Envoyé par sovitec Voir le message
    La correction était simple, je me demandais juste s'il y avait eu une évolution dans le langage qui ferait que ce code ne compile plus.
    je confirme le code compile aussi Turbo Delphi 2006, mais le bug serait plutôt qu'il compile, et la correction, le comportement que tu as sous 2010.
    Maintenant, le mot clé const en Delphi a toujours souffert de quelques bizarreries - empruntant certains principes d'autres langages, mais pas complètement (surtout depuis l'ajout de méthode dans les record).

    Citation Envoyé par Paul TOTH Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    type
      TColors = array of TRGBQuad;
    procedure GammaCorrection(Gamma: Single; var Colors: TColors);
    La définition de type change la signature de la méthode en tableau dynamique (moins générique ici), et du coup le var n'est plus utile .

    Cela devrait suffire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure GammaCorrection(Gamma: Single; var Colors: array of TRGBQuad);

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 815
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 815
    Points : 13 532
    Points
    13 532
    Par défaut
    Le pointeur Colors n'est pas modifié par cette procédure. Seul le contenu du tableau l'est. Const est parfaitement adapté à cette situation et il n'y a aucune bizarrerie là-dedans .

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Le pointeur Colors n'est pas modifié par cette procédure. Seul le contenu du tableau l'est. Const est parfaitement adapté à cette situation et il n'y a aucune bizarrerie là-dedans .
    oui mais c'est un usage batard, on indique que le pointeur ne sera pas modifiée mais les données pointées sont modifiables.

    en fait l'usage de const pour Delphi < 2010 est équivalent à "in", la valeur du pointeur n'est pas modifiable en retour contrairement à un "var".

    manifestement, depuis Delphi 2010 un paramètre constant est non modifiable, ce qui n'est pas choquant non plus...'in' qui ne servait pas à grand chose jusqu'alors prend tout son sens

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 815
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 815
    Points : 13 532
    Points
    13 532
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    oui mais c'est un usage batard, on indique que le pointeur ne sera pas modifiée mais les données pointées sont modifiables.
    Bien sûr et pour moi; c'est logique ! Dans le cas d'un tableau dynamique, il s'agit de deux allocations mémoire différentes .
    Le problème tourne plutôt autour de la compréhension de la différence entre un tableau: dynamique et statique.

    Ma license d'évaluation D2010 a expiré depuis longtemps et ne peut pas faire le test, mais je doute que la philosophie Delphi ait fondamentalement changé depuis D2009.

  8. #8
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Le pointeur Colors n'est pas modifié par cette procédure. Seul le contenu du tableau l'est. Const est parfaitement adapté à cette situation et il n'y a aucune bizarrerie là-dedans .
    Dans la version que donne sovitec, l'argument Colors est un "paramètre tableau ouvert".

    Si cela avait été un tableau dynamique (comme dans l'exemple de Paul TOTH), là en effet, ce qui aurait été passé, c'est la référence du tableau dynamique, donc const ou var s'applique sur cette dernière et non sur les éléments du tableau.

    Mais pour un paramètre tableau ouvert, c'est une sémantique par valeur qui est appliquée ; en l'absence de var ou const, il y a recopie du tableau (même si en interne ce type de passage d'argument est géré par un pointeur + un entier spécifiant l'index du dernier élément du tableau).
    Lorsque l'on applique const ou var sur ce paramètre, il est alors passé par référence et dans le cas de const, ses éléments sont non affectables.

    Exemple : ce code ne compile pas sous Delphi 2006 (et sans doute autre)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure GammaCorrection(Gamma: Single; const Colors: array of TRGBQuad);
    const
      Inv255 = 1.0 / 255;
    var
      i: Integer;
      InvGamma: double;
    begin
      InvGamma := 1.0/Gamma;
      for i := Low(Colors) to High(Colors) do
      begin
          Colors[i].rgbRed   := Round(255 * Power(Colors[i].rgbRed   * Inv255, InvGamma));
          Colors[i].rgbGreen := Round(255 * Power(Colors[i].rgbGreen * Inv255, InvGamma));
          Colors[i].rgbBlue	 := Round(255 * Power(Colors[i].rgbBlue  * Inv255, InvGamma));
      end;
    end;
    C'est l'usage du with qui faisait sauter la constance (donc c'était un bug).

    Les autres bizarreries du const que je sous entendait, ce sont les comportements possibles avec l'ajout des méthode dans les record.
    Soit le type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    26
    27
    28
    29
    type
     
    TRec = record
      FInt : Integer;
      function GetInt : Integer;
      procedure SetInt(const AInt : Integer);
    end;
     
     
    { TRec }
    function TRec.GetInt: Integer;
    begin
      Result := Self.FInt;
    end;
     
    procedure TRec.SetInt(const AInt: Integer);
    begin
      Self.FInt := AInt;
    end;
     
    function TRec_GetInt(const Self : TRec): Integer;
    begin
      Result := Self.FInt;
    end;
     
    procedure TRec_SetInt(var Self : TRec; const AInt: Integer);
    begin
      Self.FInt := AInt;
    end;
    Voici ce que l'on peut obtenir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure Test(const ARec : TRec);
    var I : Integer;
    begin
      I := ARec.FInt;
      //ARec.FInt := 1; Erreur -> OK
     
      I := TRec_GetInt(ARec);
      //TRec_SetInt(ARec, 1); Erreur -> OK
     
      I := ARec.GetInt;
      ARec.SetInt(1); // Oups ?!? pas d'erreur ?!?
    end;
    En C++ par exemple, il est possible de définir les fonctions membres qui ne modifient pas l'instance et seuls celles-ci sont invocables dans un contexte const.
    Par analogie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    procedure TRec_SetInt(var Self : TRec; const AInt: Integer); <=> procedure TRec.SetInt(const AInt: Integer);
     
    function TRec_GetInt(const Self : TRec): Integer; <=> function TRec.GetInt: Integer; const; // ? (écriture inexistante - pour l'instant ? - en Delphi)

  9. #9
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 815
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 815
    Points : 13 532
    Points
    13 532
    Par défaut
    Citation Envoyé par gb_68 Voir le message
    Exemple : ce code ne compile pas sous Delphi 2006 (et sans doute autre)
    Au risque de te déplaire, ce code compile parfaitement sous D2009 .

  10. #10
    Membre confirmé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Points : 546
    Points
    546
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Au risque de te déplaire, ce code compile parfaitement sous D2009 .
    Et sous Delphi 2006 (Turbo), il y a bien 3 erreurs E2064 , une à chaque ligneFaudrait voir ce que cela donne avec d'autres versions de Delphi (parce que là ça devient vraiment chaotique cette histoire de const ).

  11. #11
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 815
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 815
    Points : 13 532
    Points
    13 532
    Par défaut
    A la lecture de ton lien, ce serait plutôt la déclaration d'une propriété en lecture seule (passée en paramètre à cette procédure) qui serait en cause et non la procédure elle-même.

Discussions similaires

  1. Modifier image selon passage de la souris
    Par beral dans le forum C++Builder
    Réponses: 4
    Dernier message: 03/10/2006, 17h49
  2. [DEBUTANT]modifier pour devenir incrémentant
    Par tripper.dim dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 16/05/2006, 14h24
  3. Comment faire pour le passage des paramètres
    Par dauphin34000 dans le forum Oracle
    Réponses: 14
    Dernier message: 25/04/2006, 14h18
  4. Réponses: 4
    Dernier message: 19/04/2006, 15h10
  5. Erreur 873 de rsync pour un passage cron
    Par GLDavid dans le forum Administration système
    Réponses: 18
    Dernier message: 14/11/2005, 14h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo