Importance d'un fichier .inl en C ++


108

Quels sont les avantages d'avoir des déclarations dans un fichier .inl? Quand aurais-je besoin d'utiliser le même?


3
FWIW, je déteste les fichiers .inl. Pourquoi diviser votre code plus que nécessaire?
Shog9

10
@ shog9: Pour séparer l'interface de l'implémentation. J'ai toujours détesté les fichiers C # et Java car il est si difficile de lire l'interface à cause de tous les détails d'implémentation de messey.
Martin York

8
@Martin - malheureusement C ++ nous donne une mauvaise combinaison des deux mondes - l'interface et une partie de l'implémentation dans l'en-tête, le reste de l'implémentation dans le fichier .cpp. Même si vous évitez les fonctions en ligne (ou les mettez dans des fichiers .inl), vous devez encombrer l'interface avec les détails embêtants des membres privés, à moins que vous ne soyez capable d'utiliser religieusement l'idiome pimpl.
Michael Burr

5
Ouais, je n'ai jamais compris l'argument selon lequel les en-têtes séparent l'interface de l'implémentation. Ils ne le font évidemment pas. Une interface ne doit pas contenir tous les membres privés.
jalf

@LokiAstari: Pour être honnête, Java / C # a un très bon outillage fournissant automatiquement le contour de l'interface. On pourrait le dire autrement: en C ++, vous devez résoudre manuellement un problème, qui peut être entièrement résolu par des ordinateurs.
bluenote10

Réponses:


140

.inlles fichiers ne sont jamais obligatoires et n'ont aucune signification particulière pour le compilateur. C'est juste une façon de structurer votre code qui fournit un indice aux humains qui pourraient le lire.

J'utilise des .inlfichiers dans deux cas:

  • Pour les définitions des fonctions en ligne.
  • Pour les définitions des modèles de fonctions.

Dans les deux cas, je mets les déclarations des fonctions dans un fichier d'en-tête, qui est inclus par d'autres fichiers, puis je #includele .inlfichier en bas du fichier d'en-tête.

Je l'aime car il sépare l'interface de l'implémentation et rend le fichier d'en-tête un peu plus facile à lire. Si vous vous souciez des détails de l'implémentation, vous pouvez ouvrir le .inlfichier et le lire. Sinon, vous n'êtes pas obligé.


2
En effet, il s'agit principalement de séparer l'interface de l'implémentation.
Pavel Minaev

1
J'ai également vu .ipp et .ixx utilisés pour les définitions en ligne et .tpp et .txx pour le modèle un.
AProgrammer

1
Par exemple, la bibliothèque GNU Standard C ++ utilise .tccpour les fichiers d'implémentation de modèle.
musiphil

2
@NickMeyer glmutilise .hpp et .inl exactement de la même manière que vous avez mentionné ci-dessus. Bon à savoir, merci pour la bonne réponse :)
legends2k

Alors, est-ce comme un en-tête?
Aaron Franke

90

Nick Meyer a raison: le compilateur ne se soucie pas de l'extension du fichier que vous incluez, donc des choses comme ".h", ".hpp", ".hxx", ".hh", ".inl", ".inc", etc. sont une convention simple, pour préciser ce que les fichiers sont censés contenir.

Le meilleur exemple est les fichiers d'en-tête STL qui n'ont aucune extension.

Habituellement, les fichiers ".inl" contiennent du code en ligne (d'où l'extension ".inl").

Ces fichiers ".inl" sont une nécessité lorsque vous avez un cycle de dépendance entre le code d'en- tête .

Par exemple:

// A.hpp
struct A
{
    void doSomethingElse()
    {
       // Etc.
    }

    void doSomething(B & b)
    {
       b.doSomethingElse() ;
    }
} ;

Et:

// B.hpp
struct B
{
    void doSomethingElse()
    {
       // Etc.
    }

    void doSomething(A & a)
    {
       a.doSomethingElse() ;
    }
} ;

Il n'y a aucun moyen que vous le fassiez compiler, y compris en utilisant la déclaration forward.

La solution est alors de décomposer la définition et l'implémentation en deux types de fichiers d'en-tête:

  • hpp pour la déclaration / définition d'en-tête
  • inl pour l'implémentation de l'en-tête

Ce qui se décompose en l'exemple suivant:

// A.hpp

struct B ;

struct A
{
    void doSomethingElse() ;
    void doSomething(B & b) ;
} ;

Et:

// A.inl
#include <A.hpp>
#include <B.hpp>

inline void A::doSomethingElse()
{
   // Etc.
}

inline void A::doSomething(B & b)
{
   b.doSomethingElse() ;
}

Et:

// B.hpp

struct A ;

struct B
{
    void doSomethingElse() ;
    void doSomething(A & a) ;
} ;

Et:

// B.INL
#include <B.hpp>
#include <A.hpp>

inline void B::doSomethingElse()
{
   // Etc.
}

inline void B::doSomething(A & a)
{
   a.doSomethingElse() ;
}

De cette façon, vous pouvez inclure le fichier ".inl" dont vous avez besoin dans votre propre source, et cela fonctionnera.

Encore une fois, les noms de suffixe des fichiers inclus ne sont pas vraiment importants, seulement leurs utilisations.


5
Ceci explique le réel avantage (ou nécessité) de la séparation et aurait dû être choisi comme réponse.
musiphil

1
Si la fonction n'était pas en ligne, vous utiliseriez un fichier .cpp standard pour la partie implémentation?
Bublafus

1
@Bublafus If the function were not inline, you would you standard .cpp file for the implementation part?:: Peut-être. Les modèles sont des exemples de code qui ne peuvent généralement pas être masqués dans les fichiers .CPP, donc dans ce cas, le fichier .INL serait obligatoire.
paercebal

32

Puisque personne d'autre ne l'a mentionné:

L'utilisation de fichiers .inl pour stocker vos fonctions en ligne peut être utile pour accélérer les compilations.

Si vous n'incluez que les déclarations (.h) là où vous avez besoin de déclarations, et n'incluez que les implémentations en ligne (.inl) là où vous en avez besoin (c'est-à-dire probablement uniquement dans .cpp et autres fichiers .inl, pas dans .h), il peut avoir un effet bénéfique sur vos dépendances d'en-tête.

Cela peut être une victoire significative sur des projets plus importants avec de nombreuses classes interactives.


7
+1: le monde est définitivement un endroit différent lorsque vous gérez des millions de lignes de code et des milliers de fichiers.
gatorfax

donc vous ne devriez jamais inclure .inl dans les fichiers d'en-tête? J'ai toujours eu le sentiment que .inl devait être placé au bas des fichiers d'en-tête car les fonctions en ligne nécessitent une déclaration et une implémentation pour être accessibles en même temps.
Icebone1000

1
Icebone1000 tous les modules qui incluent l'en-tête ne veulent pas nécessairement utiliser les fonctions en ligne, ils n'ont donc pas besoin que les implémentations soient lues, ils ne sont pas tenus d'être présents s'ils ne sont pas utilisés.
Andy J Buchanan

1
Je ne comprends pas comment cela peut être plus rapide, car le compilateur doit faire plus de travail pour inclure et combiner les unités de traduction.
Nikos

1
@Nikos Je pense qu'il voulait dire plus rapide par rapport à mettre toutes vos fonctions en ligne dans vos fichiers d'en-tête.
CoffeeTableEspresso

3

D'après mon expérience, les fichiers .inl sont utilisés pour définir des fonctions en ligne. Lorsqu'ils sont dans un fichier .inl, le fichier peut être inclus dans un en-tête pour obtenir des fonctions en ligne et dans un fichier .c pour obtenir des définitions de fonctions régulières.

De cette façon, la même source peut plus facilement fonctionner avec des compilateurs qui n'ont pas de support de fonction en ligne ainsi que des compilateurs qui le font.

Ils sont généralement utilisés avec du code C simple, pas souvent avec du code C ++ car tous les compilateurs C ++ prennent en charge les fonctions en ligne.


Je ne vois pas l'intérêt de faire cela juste pour obtenir le support C. Pour C, vous ne devez que conditionnellement #define inline staticet définir vos fonctions en ligne dans l'en-tête.
Pavel Minaev

Je suppose que cela évite que plusieurs copies de la même fonction se retrouvent dans le binaire. Je dis juste que j'ai vu des fichiers .inl utilisés de cette façon, non pas que ce soit la seule technique (ou même la meilleure).
Michael Burr

1

Je crois que c'est juste une convention de dénomination pour un fichier "en-tête" comprenant du code en ligne. c'est pour que les fichiers .h puissent contenir des définitions et les fichiers .inl contiennent du code en ligne qui est nécessaire pour les modèles.

Je ne pense pas qu'il y ait autre chose qu'une convention de dénomination pour clarifier l'objectif du fichier

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.