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