minimiser la recompilation quand on utilise des fonctions inline

 

La plupart de mes classes ont des méthodes inline : Get/Set, operateurs, constructeurs simples, etc. Par souci de lisibilité j'ai l'habitude de séparer leur implémentation de la déclaration de la classe, en les mettant dans un fichier .inl (comme les MFC). Le fichier .inl est inclus à la fin du fichier .h, donc mise à part la considération esthétique c'est exactement la même chose que de coder le corps de la fonction dans la classe elle-même : si une seule fonction inline est modifiée, chaque fichier .cpp incluant cette classe directement ou non va être recompilé, ce qui peut prendre un certain temps dans un gros projet.

Etant donné que je développe la plupart du temps en mode debug (et compile en release lorsque tout semble OK), et que les fonctions ne sont par défaut pas inlinées du tout en mode debug avec Visual C++, il y a une solution pour minimiser le problème de recompilation : mettre les fonctions à inliner dans le fichier .cpp pour un build en debug, et dans le fichier .h pour un build en release (afin qu'elles puissent effectivement être inlinées). Prenons un exemple pour voir comment cela fonctionne ; supposons que j'ai la classe suivante :

//--------------------------------------------------------------------------------------------------------------------//
// fichier VectMat.h

#ifndef   _VECTMAT_H_
#define   _VECTMAT_H_

class CVect2D
  {
  public:

    // constructors

    inline          CVect2D             (void);
    inline          CVect2D             (const float fD);                                 // x=y=fD
    inline          CVect2D             (const float fX, const float fY);                 // x=fX; y=fY

[... etc ...]
  };

#include  "VectMat.inl"
#endif // _VECTMAT_H_

//--------------------------------------------------------------------------------------------------------------------//
// fichier VectMat.inl

#ifndef   _VECTMAT_INL_
#define   _VECTMAT_INL_

inline CVect2D::CVect2D()                                             // ne rien faire
  {}

inline CVect2D::CVect2D(const float fD)                               // x=y=fD
  { m_fV[_X_] = m_fV[_Y_] = fD; }

inline CVect2D::CVect2D(const float fX,const float fY)                // x=fX; y=fY
  { m_fV[_X_] = fX; m_fV[_Y_] = fY; }

[... etc ...]

#endif // _VECTMAT_INL_

//--------------------------------------------------------------------------------------------------------------------//
// fichier VectMat.cpp

#include  "stdafx.h"
#include  "VectMat.h"

[... implémentation des méthodes qui ne sont pas inline ...]


Comme affirmé précédemment, toute modification dans VectMat.inl provoquera la recompilation de chaque fichier .cpp qui inclut VectMat.h, et les vecteurs sont le genre de classes qui sont utilisées à un tas d'endroits. Maintenant voyons la version modifiée :

//--------------------------------------------------------------------------------------------------------------------//
// fichier VectMat.h

#ifndef   _VECTMAT_H_
#define   _VECTMAT_H_

#ifdef    _DEBUG
#define    INLINE
#else
#define    INLINE                       inline
#endif

class CVect2D
  {
  public:

    // constructors

    INLINE          CVect2D             (void);
    INLINE          CVect2D             (const float fD);                                 // x=y=fD
    INLINE          CVect2D             (const float fX, const float fY);                 // x=fX; y=fY

[... etc ...]
  };

#ifndef   _DEBUG
#include  "VectMat.inl"
#endif
#endif // _VECTMAT_H_

//--------------------------------------------------------------------------------------------------------------------//
// fichier VectMat.inl

#ifndef   _VECTMAT_INL_
#define   _VECTMAT_INL_

INLINE CVect2D::CVect2D()                                             // ne rien faire
  {}

INLINE CVect2D::CVect2D(const float fD)                               // x=y=fD
  { m_fV[_X_] = m_fV[_Y_] = fD; }

INLINE CVect2D::CVect2D(const float fX,const float fY)                // x=fX; y=fY
  { m_fV[_X_] = fX; m_fV[_Y_] = fY; }

[... etc ...]

#endif // _VECTMAT_INL_

//--------------------------------------------------------------------------------------------------------------------//
// fichier VectMat.cpp

#include  "stdafx.h"
#include  "VectMat.h"

#ifdef _DEBUG #include "VectMat.inl" #endif
[... implémentation des méthodes qui ne sont pas inline ...]

A présent lorsque l'on compile en mode debug, seul VectMat.cpp est affecté per les changements de VectMat.inl.
Résumons les modifications (montrées en rouge) :

* dans le fichier .h :
- une macro INLINE est définie
- toutes les occurrences du mot-clé 'inline' sont remplacées par 'INLINE'
- VectMat.inl est seulement inclus pour un build en release

* dans le fichier .inl :
- les mots-clés 'inline' sont remplacés par 'INLINE'

* dans le fichier .cpp :
- VectMat.inl est inclus pour un build en debug (en plus de VectMat.h)


Note : cet article a d'abord été posté sur Flipcode, où vous pouvez lire les commentaires (en anglais) d'autres programmeurs.


haut de la page