Fonctions inline : mise au point

Fonctions inline : mise au point - C++ - Programmation

Marsh Posté le 13-11-2006 à 17:12:55    

Salut,
 
J'ai besoin d'une petite précision concernant les fonctions inline : si j'ai bien compris, il n'est pas possible d'utiliser dans un programme une fonction inline définie dans une classe utilisée par ce programme ? Par exemple, un truc comme :
 
maClasse.h :

Code :
  1. class maClasse
  2. {
  3.       ...
  4.       void maFonction();
  5.       ...
  6. };


maClasse.cxx :

Code :
  1. #include "maClasse.h"
  2. ...
  3. inline void maClasse::maFonction()
  4. {
  5.       ...
  6. }
  7. ...


monProgramme.C :

Code :
  1. int main()
  2. {
  3.       ...
  4.       maClasse *exemple=new maClasse();
  5.       exemple->maFonction();
  6.       ...
  7. }


est interdit ?
 
Merci.


Message édité par SkippyleGrandGourou le 14-11-2006 à 11:11:13
Reply

Marsh Posté le 13-11-2006 à 17:12:55   

Reply

Marsh Posté le 13-11-2006 à 20:53:14    

ta fonction inline s'appelle maClasse::maFonction() et pas juste maFonction()

Reply

Marsh Posté le 14-11-2006 à 11:12:10    

jesus_christ a écrit :

ta fonction inline s'appelle maClasse::maFonction() et pas juste maFonction()

:whistle: Oups ! Biens sûr... Corrigé. Mais ça répond pas à ma question ...  ;)


Message édité par SkippyleGrandGourou le 14-11-2006 à 11:12:31
Reply

Marsh Posté le 14-11-2006 à 11:44:57    

Ben, la question n'a pas de sens, si?
Quel est l'intérêt d'écrire une méthode que tu ne peux pas appeler? :D

Reply

Marsh Posté le 14-11-2006 à 12:24:46    

Bon déjà tu dois définir ta fonction comme public (par defaut je pense que c'est private dans ta classe) i.e.

Code :
  1. class xxxx
  2. {
  3. public:
  4. etc...
  5. }


 
Sinon inline a rien avoir avec l'accés ou pas de ta méthode, c'est une instruction pour ton compilateur qui s'il n'est pas trop pourri optimise trés bien le code tout seul, donc tu peux oublier les inline à moins que tu fasses du code complexe (style méta-programmation par exemple) ce qui n'est apparement pas le cas ;) .

Message cité 2 fois
Message édité par ElDesdichado le 14-11-2006 à 12:25:31
Reply

Marsh Posté le 14-11-2006 à 13:48:57    

IrmatDen a écrit :

Ben, la question n'a pas de sens, si?
Quel est l'intérêt d'écrire une méthode que tu ne peux pas appeler? :D

Ben si, la question c'est justement que je cherche une confirmation du fait de ce que je veux faire est interdit...  :p  
 

ElDesdichado a écrit :

Bon déjà tu dois définir ta fonction comme public (par defaut je pense que c'est private dans ta classe)

Oui oui, bien sûr (par défaut mes méthodes sont publiques (pas les variables), et c'est au moment du grand ménage que je les passe en private).
 

ElDesdichado a écrit :

Sinon inline a rien avoir avec l'accés ou pas de ta méthode,

Pourtant la compilation de l'exemple ci-dessus me donne :

Code :
  1. undefined reference to `maClasse::maFonction()'
  2. collect2: ld returned 1 exit status


 

ElDesdichado a écrit :

c'est une instruction pour ton compilateur qui s'il n'est pas trop pourri optimise trés bien le code tout seul, donc tu peux oublier les inline

Oui mais je voudrais essayer quand même, histoire de comprendre un peu mieux comment ça marche... Pis si cette instruction existe, c'est pas pour rien, si ?  :??:  
 

ElDesdichado a écrit :

à moins que tu fasses du code complexe (style méta-programmation par exemple) ce qui n'est apparement pas le cas ;) .

Je tiens à préciser que mes codes sont un tout petit peu plus complexes que l'exemple donné ici...  :lol:

Message cité 1 fois
Message édité par SkippyleGrandGourou le 14-11-2006 à 13:50:14
Reply

Marsh Posté le 14-11-2006 à 14:12:47    

SkippyleGrandGourou a écrit :

la compilation de l'exemple ci-dessus me donne :

Code :
  1. undefined reference to `maClasse::maFonction()'
  2. collect2: ld returned 1 exit status


Il faut que ta fonction soit définie (et pas seulement déclarée) dans le header. Du coup, elle ne doit plus apparaître dans le fichier .c


---------------
TriScale innov
Reply

Marsh Posté le 14-11-2006 à 14:44:09    

franceso a écrit :

Il faut que ta fonction soit définie (et pas seulement déclarée) dans le header. Du coup, elle ne doit plus apparaître dans le fichier .c

Ok, en fait ce qui m'a induit en erreur est que dans les FAQ et cours C++ on voit souvent des trucs genre :

Code :
  1. class maClasse
  2. {
  3.   public:
  4.     ...
  5.     void maFonction();
  6.     ...
  7. };
  8. inline void maClasse::maFonction()
  9. {
  10.     ...
  11. }


Ce que, ayant l'habitude de passer mes déclarations dans un fichier différent du header, j'interprète naturellement comme :

Code :
  1. // Fichier maClasse.h :
  2. class maClasse
  3. {
  4.   public:
  5.     ...
  6.     void maFonction();
  7.     ...
  8. };
  9. // Fichier maClasse.cxx :
  10. inline void maClasse::maFonction()
  11. {
  12.     ...
  13. }

Alors que tout doit être dans le .h, effectivement. Merci, je crois que j'ai compris.  :jap:

Reply

Marsh Posté le 14-11-2006 à 20:03:17    

ElDesdichado a écrit :

Bon déjà tu dois définir ta fonction comme public


Pas nécessairement.
 

Citation :

[...] tu peux oublier les inline à moins que tu fasses du code complexe (style méta-programmation par exemple).


Je ne sais pas ce que tu entends par code complexe, mais selon l'idée que je m'en fais, la méta-programmation en est un contre exemple cinglant.

Reply

Marsh Posté le 16-11-2006 à 16:53:42    

Effectivement ce n'est pas nécessaire, mais au vu de son exemple c'était le plus logique, non?
 
En terme de lecture aisée du code (cf. le code source de BOOST), par contre bien fait une oeuvre d'art.


Message édité par ElDesdichado le 16-11-2006 à 16:55:36
Reply

Marsh Posté le 16-11-2006 à 16:53:42   

Reply

Marsh Posté le 17-11-2006 à 01:32:39    

oublie l'inline.
lis ça par exemple:
http://www.codeproject.com/tips/gloption.asp

Reply

Marsh Posté le 17-11-2006 à 11:43:44    

Oh t'inquiètes pas, j'ai laissé tombé, c'était surtout pour comprendre. Maintenant je préfère pas encombrer mon .h, donc tant pis pour les inline. Par contre, arrête-moi si je me trompe, mais ton lien là, c'est du Visual C++ .NET, c'est du pur Windows, non ?

Reply

Marsh Posté le 17-11-2006 à 16:07:07    

bin c'est exemple d'optimisation ne nécessitant pas d'inline avec Visual C++ 7.
tu dois avoir la même chose sous plein de compilos maintenant.

Reply

Marsh Posté le 17-11-2006 à 18:16:10    

bjone a écrit :

bin c'est exemple d'optimisation ne nécessitant pas d'inline avec Visual C++ 7.
tu dois avoir la même chose sous plein de compilos maintenant.


GCC ne le propose que pour le C, et IMA pour C++ est en cours de développement.
Une autre technique, plus puissante, est de faire de l'optimisation à l'édition de lien. Sun CC en a, GCC bientôt,et surement d'autres.
Et cela permet de faire plein d'autres choses que de l'inlining.

Reply

Marsh Posté le 17-11-2006 à 23:02:51    

VC++ 7 et 8 ont le link-time code generation

Reply

Marsh Posté le 19-11-2006 à 11:41:39    

Difficile d'imaginer qque chose de plus inutile qu'inline, vu que ce n'est qu'une suggestion et non un contrat; donc une grande source de confusion.
 
Pour les compilateurs modernes - msvc/gcc/icc récents - la déclaration et définition conjointe d'une fonction est une incitation bien plus impérative à l'inlining; soupoudrer une telle déclaration avec un inline est superfétatoire.
 
Si vous voulez contraindre le compilateur à inliner, utiliser les extensions ad hoc

Code :
  1. // MSVC ou ICC en émulation MSVC
  2. #define FINLINE     __forceinline
  3. #define NOINLINE    __declspec(noinline)
  4. // GCC ou ICC en émulation GCC
  5. #define FINLINE     __attribute__((always_inline))
  6. #define NOINLINE    __attribute__((noinline))


 
Généralement il y a d'autres moyens de controle, voir http://gcc.gnu.org/onlinedocs/gcc/ [...] Attributes et 'flatten' par exemple.
 
 
Le projet de LTO, Link Time Optimization, est en chantier pour GCC, mais il sait déjà faire ce genre de passe sur un module C++ avec -funit-at-a-time (déclenché à -O1) donc une approche à la cat *.cc|g++ est parfaitement envisageable. Mais délicate :)

Reply

Marsh Posté le 19-11-2006 à 12:26:46    

tbp a écrit :

Le projet de LTO, Link Time Optimization, est en chantier pour GCC, mais il sait déjà faire ce genre de passe sur un module C++ avec -funit-at-a-time (déclenché à -O1)


Sauf que ce n'est pas *du tout* le même genre de passe.
(déclenché à -02 et -O3 d'aprés la documentation de 4.1.1)
 

Citation :

donc une approche à la cat *.cc|g++ est parfaitement envisageable. Mais délicate :)


Cette approche, c'est à peu près l'approche de -fwhole-programm --combine, et qui n'a non plus rien à voir avec l'approche LTO.

Reply

Marsh Posté le 19-11-2006 à 15:00:44    

++fab a écrit :

Sauf que ce n'est pas *du tout* le même genre de passe.
(déclenché à -02 et -O3 d'aprés la documentation de 4.1.1)
 

Citation :

donc une approche à la cat *.cc|g++ est parfaitement envisageable. Mais délicate :)


Cette approche, c'est à peu près l'approche de -fwhole-programm --combine, et qui n'a non plus rien à voir avec l'approche LTO.


 
Je persiste et signe,
a) -O1, http://gcc.gnu.org/onlinedocs/gcc/ [...] ze-Options
b) --combine est inutilisable avec le C++, http://gcc.gnu.org/onlinedocs/gcc/ [...] combine-82
c) c'est en bien en gros la même chose, c.a.d. 'unit-at-a-time' est un sous-ensemble de ce que l'on attend de la LTO: changement de convention d'appel, inlining... j'en passe et des meilleurs, cf la doc.
 
Evidement la LTO requiert l'usage d'une description intermédiaire et unit-at-a-time/whole-program non. Mais fondamentalement...
 
 
 

Reply

Marsh Posté le 19-11-2006 à 18:09:18    


Je ne sais pas à quelle version de gcc se manuel se rapporte, mais sous 4.x, c'est -O2 ou -O3.
 

Citation :

c) c'est en bien en gros la même chose, c.a.d. 'unit-at-a-time' est un sous-ensemble de ce que l'on attend de la LTO: changement de convention d'appel, inlining... j'en passe et des meilleurs, cf la doc.


Oui. Pour la doc, d'après ce que j'ai pu comprendre, ce que va faire LTO n'est pas encore complètement fixé.
 

Citation :

Evidement la LTO requiert l'usage d'une description intermédiaire et unit-at-a-time/whole-program non. Mais fondamentalement...


fondamentalement oui, mais après tout dépend de ce que tu veux que GCC fasse, et donc ce que tu mets dans la description intermédiaire. Si l'ambition est de réduire le nombre d'instanciation effective de template, l'implémentation de ceci côté LTO est apparemment complexe.

Reply

Marsh Posté le 19-11-2006 à 18:46:08    

++fab a écrit :

Je ne sais pas à quelle version de gcc se manuel se rapporte, mais sous 4.x, c'est -O2 ou -O3.


4.3, mais si mes souvenirs sont bons c'était déjà le cas pour la 4.2.
 
 

++fab a écrit :

fondamentalement oui, mais après tout dépend de ce que tu veux que GCC fasse, et donc ce que tu mets dans la description intermédiaire. Si l'ambition est de réduire le nombre d'instanciation effective de template, l'implémentation de ceci côté LTO est apparemment complexe.


Avec la LTO le compilateur est réduit à un front-end/parser et il doit y avoir une description intermédiaire pour effectuer la jonction avec la phase finale. Celà indépendament de tout problème d'optimisation, templates inclus.
http://gcc.gnu.org/ml/gcc/2006-08/msg00532.html pour une des nombreuses discussions sur le sujet (note: dwarf n'est plus à l'ordre du jour).
 
Par contre la LTO doit permettre d'utiliser des 'modes' conflictuels, genre x87regparm d'un coté mais de l'autre, ce ne permet pas un cat *.cc|g++. Ca et d'être encore plus aggressif, violant qques règles si besoin est, puisque que le compilateur a l'accord implicite de l'utilisateur.

Message cité 1 fois
Message édité par tbp le 19-11-2006 à 19:04:57
Reply

Marsh Posté le 19-11-2006 à 19:53:32    

tbp a écrit :

4.3, mais si mes souvenirs sont bons c'était déjà le cas pour la 4.2.


Ah oui. Donc -O1 probalement pour l'avenir non encore releasé, et -O2 -O3 pour 4.0.x et 4.1.x.
 

Citation :

Par contre la LTO doit permettre d'utiliser des 'modes' conflictuels, genre x87regparm d'un coté mais de l'autre, ce ne permet pas un cat *.cc|g++.

Je ne comprend pas ce que tu veux dire; et je ne vois pas comment LTO pourrait résoudre ce genre de problème.
 

Citation :

Ca et d'être encore plus aggressif, violant qques règles si besoin est, puisque que le compilateur a l'accord implicite de l'utilisateur.


Tu pourrais préciser de quelles règles tu parles ?

Message cité 1 fois
Message édité par ++fab le 19-11-2006 à 19:53:53
Reply

Marsh Posté le 19-11-2006 à 20:17:02    

++fab a écrit :

Citation :

Par contre la LTO doit permettre d'utiliser des 'modes' conflictuels, genre x87regparm d'un coté mais de l'autre, ce ne permet pas un cat *.cc|g++.

Je ne comprend pas ce que tu veux dire; et je ne vois pas comment LTO pourrait résoudre ce genre de problème.


La LTO est censée être, fonctionellement du moins, transparente pour l'utilisateur. Je peux traditionellement compiler une unité en fast-math, une autre sans et linker le tout. Il en découle qu'il faut aussi encoder dans la representation intermédiaire LTO, disons pour chaque fonction, les "options de compilation".
Ce genre de facilité (pouvoir basculer des options en pleine course, pour une fonction ou un block, exemple type: unroll) manque à gcc depuis des lustres et devient une extension naturelle de la LTO.
 

++fab a écrit :

Tu pourrais préciser de quelles règles tu parles ?


Pas franchement vu qu'a l'instant T, il n'y a rien de tangible :)
Les candidats sont comme tjs aliasing, visibilité, ordre, code mort etc... pour un festival de bugs latents.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed