Guru Of the Week n° 34 : les déclarations anticipées

Difficulté : 8 / 10
Les déclarations anticipées sont un moyen formidable d'éliminer les dépendances inutiles lors de la compilation. Mais voici un exemple de piège typique des déclarations anticipées... Comment l'éviteriez-vous ?

Retrouvez l'ensemble des Guru of the Week sur la page d'index.

N'hésitez pas à commenter cet article ! 8 commentaires Donner une note à l'article (5)

Article lu   fois.

Les deux auteurs

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Problèmes

I-A. Question Junior

Les déclarations anticipées sont des outils très utiles. Dans ce cas, elles ne fonctionnent pas comme attendu par le développeur. Pourquoi les lignes marquées sont-elles des erreurs ?

 
Sélectionnez
// file f.h
#ifndef XXX_F_H_
#define XXX_F_H_

class ostream;  // erreur
class string;   // erreur

string f( const ostream& );

#endif

I-B. Question Guru

Sans inclure aucun autre fichier, pouvez-vous écrire les déclarations anticipées correctes pour ostream et string ci-dessus ?

II. Solutions

II-A. Question Junior

Les déclarations anticipées sont des outils très utiles. Dans ce cas, elles ne fonctionnent pas comme attendu par le développeur. Pourquoi les lignes marquées sont-elles des erreurs ?

Malheureusement, vous ne pouvez pas déclarer par anticipation ostream et string de cette façon, parce que ce ne sont pas des classes... ce sont des typedefs de template.

(C'est vrai, autrefois vous déclariez par anticipation ostream et string de cette façon, mais c'était il y a plusieurs années et ce n'est plus possible en C++ standard.)

II-B. Question Guru

Sans inclure aucun autre fichier, pouvez-vous écrire les déclarations anticipées correctes pour ostream et string ci-dessus ?

Malheureusement, la réponse est qu'il n'y a pas de façon standard ni portable de le faire. La norme dit :

Ajouter des déclarations ou des définitions à l'espace de nom std ou à des espaces de nom au sein de l'espace de nom std n'est pas défini pour un programme C++, sauf spécifié autrement.

Entre autres choses, cela permet aux vendeurs de compilateur de fournir des implémentations de la bibliothèque standard qui ont davantage de paramètres template pour les templates de bibliothèque que ce que la norme exige (convenablement paramétrés par défaut, bien sûr, pour rester compatible).

Le mieux que vous puissiez faire (ce qui n'est pas une solution au problème "sans inclure aucun autre fichier") est ceci :

 
Sélectionnez
#include <iosfwd>
#include <string>

L'en-tête iosfwd contient bona fide une déclaration anticipée. Pas l'en-tête string. C'est tout ce que vous pouvez faire qui soit encore pratique. Heureusement, faire une déclaration anticipée de string et ostream n'est pas un gros problème en pratique, car ces lignes sont généralement courtes et largement utilisées. Cela vaut aussi pour la plupart des en-têtes standards. Toutefois, faites attention aux pièges et résistez à la tentation de lancer des templates à déclaration anticipée — ni quoi que ce soit d'autre — appartenant à l'espace de noms std... c'est réservé aux éditeurs de compilateurs et de bibliothèque et à eux seuls.

III. Remerciements

Cet article est une traduction par l'équipe de la rubrique C++ de l'article de Herb Sutter publié sur Guru of the Week. Vous pouvez retrouver cet article dans sa version originale sur le site de Guru of the Week : Forward DeclarationsForward Declarations.

Merci à Luc Hermitte pour sa relecture technique, à ClaudeLELOUP, à Gurdil le nain et à jacques_jean pour leur relecture orthographique.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2009 Herb Sutter. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.