Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Compilation Firewall: avantages sans trop d'inconvenient ?

14 réponses
Avatar
Marc Boyer
Bon, dans la série "je découvre la vie", je repensais à l'idiome
Pimpl. Si j'ai tout bien compris:
- avantages:
* recompilation accélérée (indépendante de l'implémentation)
* possibilité de faire évoluer des librairies (puisqu'on a
pas à recompiler le code utilisateur)
- inconvénients:
* petit surcrois de code à écrire
* une indirection de plus à chaque accès

Hors, il me semble qu'on pourrait avoir un truc qui offre un
avanage sur deux en suprimant un inconvénient sur deux en
distinguant un mode "en développement" et un mode "optimisé".

Suffirait d'envelopper le pointeur pimpl dans une classe
qui soit un simple pointeur en mode développement (recompilation
rapide), et qui contienne vraiment l'objet en mode
optimisé.

C'est tellement évident que personne n'a trouvé intéressant
de le mentionner ou il y a un truc que j'ai raté ?

template <class T>
class Pimpl {
public:
Pimpl(int param):impl( new T(param) ){}
~Pimpl(){ delete impl; }
T& operator->(){ return *impl;}
T& operator*() { return *impl;}
private:
T* impl;
};

template <class T>
class PimplOpt {
public:
PimplOpt(int param):impl( param ){};
T& operator->(){ return impl;}
T& operator*() { return impl;}
private:
T impl;
}

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(

10 réponses

1 2
Avatar
Zouplaz
Marc Boyer - :

Bon, dans la série "je découvre la vie", je repensais à l'idiome
Pimpl. Si j'ai tout bien compris:
- avantages:
* recompilation accélérée (indépendante de l'implémentation)
* possibilité de faire évoluer des librairies (puisqu'on a
pas à recompiler le code utilisateur)
- inconvénients:
* petit surcrois de code à écrire
* une indirection de plus à chaque accès



Pourrais-tu reprendre leeeeentement ? Moi aussi je découvre la vie !! ;-)

Merci

Avatar
Loïc Joly
Marc Boyer wrote:

Bon, dans la série "je découvre la vie", je repensais à l'idiome
Pimpl. Si j'ai tout bien compris:
- avantages:
* recompilation accélérée (indépendante de l'implémentation)
* possibilité de faire évoluer des librairies (puisqu'on a
pas à recompiler le code utilisateur)
- inconvénients:
* petit surcrois de code à écrire
* une indirection de plus à chaque accès

Hors, il me semble qu'on pourrait avoir un truc qui offre un
avanage sur deux en suprimant un inconvénient sur deux en
distinguant un mode "en développement" et un mode "optimisé".

Suffirait d'envelopper le pointeur pimpl dans une classe
qui soit un simple pointeur en mode développement (recompilation
rapide), et qui contienne vraiment l'objet en mode
optimisé.

C'est tellement évident que personne n'a trouvé intéressant
de le mentionner ou il y a un truc que j'ai raté ?


Le fait que du coup le code débug est différent du code en optimisé.
Moi, ça ne me rassure pas.

--
Loïc

Avatar
Patrick Mézard
"Marc Boyer" a écrit dans le message
de news:bpi1l8$94e$
Bon, dans la série "je découvre la vie", je repensais à l'idiome
Pimpl. Si j'ai tout bien compris:
- avantages:
* recompilation accélérée (indépendante de l'implémentation)
* possibilité de faire évoluer des librairies (puisqu'on a
pas à recompiler le code utilisateur)
- inconvénients:
* petit surcrois de code à écrire
* une indirection de plus à chaque accès

Hors, il me semble qu'on pourrait avoir un truc qui offre un
avanage sur deux en suprimant un inconvénient sur deux en
distinguant un mode "en développement" et un mode "optimisé".

Suffirait d'envelopper le pointeur pimpl dans une classe
qui soit un simple pointeur en mode développement (recompilation
rapide), et qui contienne vraiment l'objet en mode
optimisé.


Les avantages liés à Pimpl sont essentiellement dus au jeu de "forward
declaration" plus inclusion minimale de header, qui limite les dépendances à
la compilation, il me semble. Le problème avec la deuxième version c'est
qu'elle nécessite la connaissance du type instancié. Les deux versions du
code nécessitent deux jeux d'include différents, et une modification
d'include n'est pas vraiment anodine.

Ca modifie aussi fortement la representation mémoire de l'objet contenant :
dans un cas l'objet subordonné est alloué de l'extérieur (dynamiquement,
allocateur particulier...), dans l'autre il sera construit dans le
contenant. Ca modifie la taille du contenant et donc peut-être la manière
dont il s'utilise (ex: on peut en allouer un tas sur la pile dans le premier
cas mais plus dans le second), et ce entre deux version du même code.

Enfin, en plus d'une réduction des dépendances, déléguer par pointeur offre
tout un tas d'avantages liés aux facilités de manipulation des pointeurs. Ca
permet d'écrire rapidement du code robuste aux exceptions, de contrôler plus
finement la durée de vie des contenus les uns par rapport aux autres, etc...

Bref, je ne suis pas convaincu que le jeu en vaille la chandelle, pas dans
le cas général en tout cas. A mon avis, Pimpl s'utilise la plupart du temps
pour des classes assez complexes (celles qui introduisent beaucoup de
dépendances à la compilation) et pour lesquelles le coût d'indirection est
souvent négligeable.

Patrick Mézard

Avatar
Marc Boyer
Loïc Joly wrote:
Marc Boyer wrote:
C'est tellement évident que personne n'a trouvé intéressant
de le mentionner ou il y a un truc que j'ai raté ?


Le fait que du coup le code débug est différent du code en optimisé.
Moi, ça ne me rassure pas.


Ben, si ça te rassure, tu peux refaire passer tous les tests
au code optimisé. Et quand tu demandes à ton compilateur d'optimiser
le code, de virer les symbole de debug, t'a bien un code différent.
Non ?

Si C++ avait une sémantique formelle, je partirais bien dans
la preuve d'équivalence des comportements...

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(


Avatar
kanze
Marc Boyer wrote in message
news:<bpi1l8$94e$...
Bon, dans la série "je découvre la vie", je repensais à l'idiome
Pimpl. Si j'ai tout bien compris:
- avantages:
* recompilation accélérée (indépendante de l'implémentation)
* possibilité de faire évoluer des librairies (puisqu'on a
pas à recompiler le code utilisateur)
- inconvénients:
* petit surcrois de code à écrire
* une indirection de plus à chaque accès

Hors, il me semble qu'on pourrait avoir un truc qui offre un
avanage sur deux en suprimant un inconvénient sur deux en
distinguant un mode "en développement" et un mode "optimisé".

Suffirait d'envelopper le pointeur pimpl dans une classe
qui soit un simple pointeur en mode développement (recompilation
rapide), et qui contienne vraiment l'objet en mode
optimisé.

C'est tellement évident que personne n'a trouvé intéressant
de le mentionner ou il y a un truc que j'ai raté ?


Assez de détails pour qu'on puisse voir ce qui se passe réelement, pour
en juger.

template <class T>
class Pimpl {
public:
Pimpl(int param):impl( new T(param) ){}
~Pimpl(){ delete impl; }
T& operator->(){ return *impl;}


T* operator->(){ return imple ; }

Non ?

T& operator*() { return *impl;}
private:
T* impl;
};

template <class T>
class PimplOpt {
public:
PimplOpt(int param):impl( param ){};
T& operator->(){ return impl;}


T* operator->(){ return &impl; }

Non ?

T& operator*() { return impl;}
private:
T impl;
}


Jusqu'à là, pas de problème. Mais comment fait tu pour organiser ton
fichier d'en-tête ?

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Marc Boyer
Patrick Mézard wrote:
"Marc Boyer" a écrit dans le message
de news:bpi1l8$94e$
Suffirait d'envelopper le pointeur pimpl dans une classe
qui soit un simple pointeur en mode développement (recompilation
rapide), et qui contienne vraiment l'objet en mode
optimisé.


Les avantages liés à Pimpl sont essentiellement dus au jeu de "forward
declaration" plus inclusion minimale de header, qui limite les dépendances à
la compilation, il me semble. Le problème avec la deuxième version c'est
qu'elle nécessite la connaissance du type instancié. Les deux versions du
code nécessitent deux jeux d'include différents, et une modification
d'include n'est pas vraiment anodine.


Cette modification d'include est minime, et en plus on a la chance
qu'elle a un comportement sur: si on a pas le lien, ça compile pas.

Ca modifie aussi fortement la representation mémoire de l'objet contenant :
dans un cas l'objet subordonné est alloué de l'extérieur (dynamiquement,
allocateur particulier...), dans l'autre il sera construit dans le
contenant. Ca modifie la taille du contenant et donc peut-être la manière
dont il s'utilise (ex: on peut en allouer un tas sur la pile dans le premier
cas mais plus dans le second), et ce entre deux version du même code.


Ca modifie la taille de contenant, oui, mais on évite
une indirection.
Après, j'ai du mal à imaginer un cas où un objet subordonné
aurait une sémantique telle qu'il ne puisse pas être alloué
de la même façon que son contenant.

Enfin, en plus d'une réduction des dépendances, déléguer par pointeur offre
tout un tas d'avantages liés aux facilités de manipulation des pointeurs. Ca
permet d'écrire rapidement du code robuste aux exceptions, de contrôler plus
finement la durée de vie des contenus les uns par rapport aux autres, etc...


Il me semble que la robustesse aux exceptions sera exactement la même.
La gestion de la durée de vie me semble ensuite quelque chose qu'on
peut "ajouter" au Pimpl, mais pas dans le paradigme de base. Non ?

Bref, je ne suis pas convaincu que le jeu en vaille la chandelle, pas dans
le cas général en tout cas. A mon avis, Pimpl s'utilise la plupart du temps
pour des classes assez complexes (celles qui introduisent beaucoup de
dépendances à la compilation) et pour lesquelles le coût d'indirection est
souvent négligeable.


Ca, j'avoue que je manque totalement d'expérience pour évaluer le
gain dans les cas ou Pimpl était utilisé.

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(


Avatar
Marc Boyer
wrote:
C'est tellement évident que personne n'a trouvé intéressant
de le mentionner ou il y a un truc que j'ai raté ?


Assez de détails pour qu'on puisse voir ce qui se passe réelement, pour
en juger.

template <class T>
class Pimpl {
public:
Pimpl(int param):impl( new T(param) ){}
~Pimpl(){ delete impl; }
T& operator->(){ return *impl;}


T* operator->(){ return imple ; }

Non ?


Oui, j'ai donné juste une base pour me faire
comprendre, pas la totalité.

T& operator*() { return *impl;}
private:
T* impl;
};

template <class T>
class PimplOpt {
public:
PimplOpt(int param):impl( param ){};
T& operator->(){ return impl;}


T* operator->(){ return &impl; }

Non ?

T& operator*() { return impl;}
private:
T impl;
}


Jusqu'à là, pas de problème. Mais comment fait tu pour organiser ton
fichier d'en-tête ?


Ben... On peut imaginer des solutions à base de #ifdef ou
d'option -I.
J'aurais une préférence pour l'option -I, avec un répertoire
decl/, dans lequel on a le Pimpl classique, et chaque fichier
MaClasseImpl.hpp ne contient que la ligne
class MaClasseImpl;
qui suffit à compiler le code utilisateur en Pimpl classique,
et un répertoire def/ dans lequel on a le faux Pimpl, et
les fichiers MaClasseImpl.hpp qui contiennent la déclaration
complète, tout ça.

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(


Avatar
Marc Boyer
Zouplaz wrote:
Marc Boyer - :
Pourrais-tu reprendre leeeeentement ? Moi aussi je découvre la vie !! ;-)


Si tu connais pas l'idiome du "Compilation Firewall", c'est normal
que tu comprennes pas.
Une des limites de C++, c'est que si tu changes la partie
privée d'une classe (donc, d'un point de vue logique, uniquement
son implémentation), tu dois recompiler le code utilisateur
(tu n'as pas à le modifier, heureusement, mais quand même).
L'idée de l'idiome Pimpl (Pointer on implementation), c'est
d'offrir une classe qui se soit que l'interface, avec un membre
privé, qui est un pointeur sur l'implémentation.
Et l'implémentation de l'interface ressemble globalement à
Truc foo(Chose param){ return pimpl->foo(param); }

Ainsi, si on change l'implémentation de la classe,
on recompile la classe, l'implémentation de son
firewall, mais rien dans le code utilisateur.

Marc Boyer
--
Lying for having sex or lying for making war? Trust US presidents :-(

Avatar
Jean-Marc Bourguet
Marc Boyer writes:

Suffirait d'envelopper le pointeur pimpl dans une classe
qui soit un simple pointeur en mode développement (recompilation
rapide), et qui contienne vraiment l'objet en mode
optimisé.


Ca m'arrive souvent de n'etre en mode developpement que sur une partie
de mon application (en fait, je n'ai jamais tout en mode
developpement): celle sur laquelle je travaille. Je craindrais
d'avoir des incoherences.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Benoit Dejean
Le Thu, 20 Nov 2003 09:31:20 +0000, Marc Boyer a écrit :

Bon, dans la série "je découvre la vie", je repensais à l'idiome
Pimpl.


c'est tellement plus joli de dire CheshireCat D

1 2