inline indiscipliné?

Please use this forum to signal bugs.
Merci d'utiliser ce forum pour signaler des bugs.

inline indiscipliné?

Postby Teaniel » Wed 2 Jan 2013 19:06

Bonjour,

Tout d'abord mes meilleurs vœux pour la nouvelle année qui commence.
Qu'elle vous apporte toutes les satisfactions et bonheurs que vous pouvez souhaiter.

Et pour bien la commencer, je me permet de vous transmettre un souci assez mal défini que j'ai actuellement avec les fonctions : il semble qu'elles aiment bien se mettre inline.
En effet, sur le projet que je suis en train de développer, il y a quelques classes (au moins deux que j'ai maintenant notées, mais sans doute plus), dont les fonctions semblent se mettre toutes seules inline. ça fait au moins trois fois que je parcours toute la classe pour décocher cette case.
Evidemment, je ne le remarque qu'au moment de générer, ce qui fait que je ne peux pas du tout vous dire quand cela se produit.
Rassurez moi ;) il n'y a pas de mécanisme permettant de cocher cette case en bloc pour toutes les fonctions d'une classe que j'utiliserais sans le faire exprès :o ... ?
Plus sérieusement, c'est un petit problème qui devient un peu gênant, dans la mesure ou si elles sont inline ces fonctions ne compilent pas (pb de dépendances), et comme ces classes commencent à s'étoffer, ça me fait perdre du temps.

Désolé d'être aussi vague, mais je ne sais effectivement pas par quel bout le prendre, ni même comment cela peut se produire. C'est pourquoi je fais appel à vous.
Par avance, merci :)
A bientôt
Marc
Teaniel
 
Posts: 75
Joined: Sun 28 Oct 2012 18:57

Re: inline indiscipliné?

Postby Bruno Pagès » Wed 2 Jan 2013 20:26

Bonjour,

Teaniel wrote:il n'y a pas de mécanisme permettant de cocher cette case en bloc pour toutes les fonctions d'une classe que j'utiliserais sans le faire exprès :o ... ?

les seuls cas de mise inline automatique sont :

  • le déplacement d'une opération vers une classe template (puisque leur opérations sont inline par défaut)
  • le fait qu'une classe devienne une classe template (il y a au moins un paramètre formel après édition alors qu'il n'y en avait pas avant, ou cela est fait par un plug-out) force à inline pour toutes ses opérations, ainsi que les opérations de ses sous classes et cela récursivement

cela hors bug évidemment
ImageAuthor of Bouml
Bruno Pagès
 
Posts: 449
Joined: Mon 20 Feb 2012 08:23
Location: France

Re: inline indiscipliné?

Postby Teaniel » Thu 3 Jan 2013 09:48

Bonjour,

Dans ce cas, je suppose qu'il y a peut-être quelque chose, car les classes visées sont le résultat d'un retro ingéniering, n'étaient pas paramétrées et leurs opérations n'étaient assurément pas inline.
Je vais essayer d'être plus attentif afin de pouvoir vous donner plus d'infos sur quand cela arrive.

Cordialement,
Marc
Teaniel
 
Posts: 75
Joined: Sun 28 Oct 2012 18:57

Re: inline indiscipliné?

Postby Teaniel » Sat 5 Jan 2013 18:18

Bonjour,

Je pense avoir trouvé une cause possible : le roundtrip.
Mon cas : une classe template, créée sous bouml, avec toutes ses opérations non inline. Avec cette classe, j'ai un certain nombre de méthodes d'implémentation (avec un paramètre effectif).
La génération donne donc deux fichiers. L'un avec la déclaration de la classe, l'autre avec la définition des fonctions.
A ce dernier fichier, j'ai ajouté des définitions de classe template (pardonnez moi le vocabulaire approximatif, mais je ne m'en rappelle jamais quand j'en ai besoin).
Ensuite, pour voir ce que cela donne, j'ai effectué un roundtrip et ai constaté les choses suivantes (qui me paraissent anormales) :
- Les fonctions dont j'avais défini le corps dans le champs "définition" de l'éditeur d'opération ont été recréées avec le corps séparé, alors même qu'elles avaient été générées à partir de ces dernières (détail annexe). Cependant pas inline (ce qui est correct).
- Toutes les opérations déjà existantes ont été mises inline automatiquement (anormal, puisque ne reflètant ni la source, ni l'état précédent).
- Aucune déclaration du type "template class OUMoins<dType::eType::tEntier>;" n'a été prise en compte (je ne sais d'ailleurs pas trop comment représenter une spécialisation de classe paramétrée en UML, c'est pourquoi j'avais procédé ainsi).
- Toutes les dépendances explicites que j'avais placées en raison de l'usage des objets référencés dans le corps des fonctions ont été marquées pour suppression. D'accord, j'ai répondu non, mais cette demande contredit encore une fois la source (les #include figuraient effectivement dans le cpp).
Voila, on avance un peu, mais là, en effet, on se trouve en face d'une classe paramétrée, alors qu'au départ je parlais d'une autre classe qui ne l'a jamais été.

Cordialement,
Marc
Teaniel
 
Posts: 75
Joined: Sun 28 Oct 2012 18:57

Re: inline indiscipliné?

Postby Bruno Pagès » Sun 6 Jan 2013 14:57

Bonjour,

De façon générale faire des allez retours entre génération et roundtrip est une mauvaise idée, le rountrip permet de mettre à jour le modèle lorsque l'on modifie les fichiers de l'extérieur, sous entendu sans modifier les classes sous Bouml, il y a des limites à ce que peut faire un reverse/roundtrip, vous devez choisir entre modifier le modèle dans Bouml ou le faire à l'extérieur. Les dépendances sont un moyen de forcer la production d'#include à la génération, mais le reverse/roundtrip ne créé jamais de dépendance que ce soit un #include ou autre, le roundtrip marque donc les dépendances pour en proposer la destruction.

Si j'ai bien compris (car j'ai beaucoup de mal à vous suivre) vous avez modifié le contenu d'un fichier source (pas le fichier d'en-tête) pour y ajoutez des définitions de classes template avec leur opérations, puis vous avez fait un roundtrip dessus. Comme vous pouvez le voir lorsque vous générez le code, les définitions des classes sont produites dans les fichiers d'en-tête, pas dans les fichiers sources, le reverse/roundtrip ne peut pas modéliser des classes pour qu'elles soient ensuite générées dans les fichiers sources. A partir du moment où vous placez une définition de classe ainsi que les définitions de ses opérations dans un même fichier alors de facto ces opérations sont inline, le fait qu'il s'agisse d'un fichier source ni change rien, le reverse/roundtrip déclare donc à raison vos opérations comme étant inline dans ce cas.
ImageAuthor of Bouml
Bruno Pagès
 
Posts: 449
Joined: Mon 20 Feb 2012 08:23
Location: France

Re: inline indiscipliné?

Postby Teaniel » Mon 7 Jan 2013 02:26

Bonjour,

C'est noté pour la première partie.
Pour ma part, je fais du roundtrip principalement pour ajouter le code des fonctions au modèle (dans qt il y a des fonctions de complétion de code très puissantes). Quelquefois aussi pour voir comment représenter un concept. C'est pourquoi, pour moi, faire une génération, puis un roundtrip puis une deuxième génération devrait aboutir à deux sources identiques. Je ne touche quasiment jamais au modèle quand j'interviens dans le code.
Sur les dépendances, mon avis personnel est cependant que, sur un reverse, elles devraient être générées si elles ne sont pas automatiques, car elles devront de toutes façons être placées. Sur un gros reverse cela peut représenter un travail important.

Deuxième partie, je précise donc ce que j'ai fait :
J'ai créé dans bouml une série de classes génériques. Dans ces classes, j'avais besoin de faire des spécialisations de fonctions. Ne sachant comment m'y prendre pour les exprimer, j'ai généré une classe, puis ajouté manuellement ses spécialisations dans le source ainsi que les instanciations, et j'ai fait un roundtrip, ce qui m'a permis de comprendre comment représenter une fonction spécialisée de classe générique avec bouml. c'est lors de ce roundtrip que toutes les fonctions de ma classe ont été forcées inline.
Pour plus de clarté, voici les fichiers de ce que j'ai donné au roundtrip :
Au risque de me répéter, ces fichiers ont été générés tels quels par bouml, sauf la fonction spécialisée et les instanciations qui ont été ajoutées à la main avant le roundtrip.
entête :
Code: Select all
#ifndef _OUMOINS_H
#define _OUMOINS_H


#include "AST/Operateurs/OpUnaire.h"
#include "Types/dDonneeQuelconque.h"
#include "Exceptions/eConversionInterdite.h"

class dEntier;
class dNombre;
class dTemps;

template<dType::eType T>
class OUMoins : public OpUnaire<T>
{
  public:
    virtual QString ToString() const;

    //Les classes drives surchargent cette fonction pour permettre la duplication de l'objet.
    //En principe se fait par l'usage du constructeur de copie et de new.
    virtual OUMoins<T> & clone() const;

    //Cette opration permet de dupliquer des objets qui sont des temporaires.
    //Se fait toujours par new, mais en effectuant un move sur la classe.
    virtual OUMoins<T> & clonerval() const;

    //Effectue l'opération portée par la classe avec l'opérande donné.
    virtual dDonneeQuelconque Effectuer(const dDonneeQuelconque & oper) throw(dDonnee::eConversionInterdite);

};

#endif
source :
Code: Select all
#include "AST/Operateurs/OUMoins.h"
#include "Types/dEntier.h"
#include "Types/dNombre.h"
#include "Types/dTemps.h"
#include <QString>

/* ----- Forcé inline après roundtrp --- */
template<dType::eType T>
QString OUMoins<T>::ToString() const
{
  return "-";
}

/* ----- Forcé inline après roundtrp --- */
//Les classes drives surchargent cette fonction pour permettre la duplication de l'objet.
//En principe se fait par l'usage du constructeur de copie et de new.
template<dType::eType T>
OUMoins<T> & OUMoins<T>::clone() const
{
  return *new auto(*this);
}

/* ----- Forcé inline après roundtrp --- */
//Cette opration permet de dupliquer des objets qui sont des temporaires.
//Se fait toujours par new, mais en effectuant un move sur la classe.
template<dType::eType T>
OUMoins<T> & OUMoins<T>::clonerval() const
{
  return *new auto(std::move(*this));
}

/* ----- Forcé inline après roundtrp --- */
//Effectue l'opération portée par la classe avec l'opérande donné.
template<dType::eType T>
dDonneeQuelconque OUMoins<T>::Effectuer(const dDonneeQuelconque &) throw(dDonnee::eConversionInterdite)
{
    throw (OpUn::eOperationUnaireInterdite(T, *this));
}

/* --- Ajouté à la main après première génération  pour effectuer un roundtrip ensuite et voir comment c'est représenté */
//Effectue l'opération portée par la classe avec l'opérande donné.
template<>
dDonneeQuelconque OUMoins<dType::eType::tEntier>::Effectuer(const dDonneeQuelconque & oper) throw(dDonnee::eConversionInterdite)
{
    return - oper.asEntier();
}

/* --- les lignes suivantes, ajoutées en même temps que les précédentes ont été ignorées (sans message d'erreur) par le roundtrip */
template class OUMoins<dType::eType::tEntier>;
template class OUMoins<dType::eType::tNombre>;
template class OUMoins<dType::eType::tTemps>;
template class OUMoins<dType::eType::tBooleen>;
template class OUMoins<dType::eType::tTexte>;
template class OUMoins<dType::eType::tDate>;
template class OUMoins<dType::eType::tReference>;
template class OUMoins<dType::eType::tType>;

Voila.
J'espère m'être mieux exprimé que la fois précédente.

Question subsidiaire : Y a-t-il un moyen de représenter les instanciations explicites de classes génériques (je trouve que créer une classe et le préciser manuellement dans le champs déclaration n'est pas génial car les macros ne permettent pas de le représenter, et qu'on ne peut pas lui donner le même nom)?

Cordialement,
Marc
Teaniel
 
Posts: 75
Joined: Sun 28 Oct 2012 18:57

Re: inline indiscipliné?

Postby Bruno Pagès » Sun 13 Jan 2013 15:35

Bonjour,

Le (re) passage en inline est lié à une erreur stupide de ma part qui ne reproduisait pas dans mes tests car les opérations n'y avaient pas d'arguments, ce sera corrigé.

A noter que template<> dDonneeQuelconque OUMoins<dType::eType::tEntier>::Effectuer(const dDonneeQuelconque & oper) ... produit actuellement une nouvelle opération à chaque roundtrip, il faut aussi que je corrige cela

Pour les instanciations explicites de classes génériques vous pouvez utiliser les "extra members", ou mieux mettre leur définitions dans celle de l'artifact. Un roundtrip demandera la destruction de ces "extra members", alors que les définitions dans l'artifact seront préservées.
ImageAuthor of Bouml
Bruno Pagès
 
Posts: 449
Joined: Mon 20 Feb 2012 08:23
Location: France

Re: inline indiscipliné?

Postby Bruno Pagès » Sat 26 Jan 2013 17:42

La version 6.4.3 est disponible

Le (re) passage en inline est corrigé ainsi que la duplication des opérations spécialisées (définies mais non déclarées)
ImageAuthor of Bouml
Bruno Pagès
 
Posts: 449
Joined: Mon 20 Feb 2012 08:23
Location: France


Return to Bug reports / Rapports de bugs

Who is online

Users browsing this forum: Google [Bot], Yahoo [Bot] and 1 guest

cron