Solution de l’exercice 9.2

Une première possibilité consiste à définir un type spécial struct manip par exemple, et de redéfinir les opérateurs pour ce type afin d’avoir l’effet souhaité ; les manipulateurs seraient alors des constantes de ce type. malheureusement cela conduit à « fermer » le processus, en ce sens qu’il est alors impossible de définir de nouveaux manipulateurs.

Une méthode plus astucieuse est utilisée en réalité. Elle consiste à noter qu’il est parfaitement possible de passer un argument de type « pointeur sur fonction » à un opérateur. Voici donc par exemple comment sont implantés les manipulateurs endl, ends et flush sur les flots de sorties :

class ostream : virtual public ios {     // ...     ostream& operator<< (ostream& (*f)(ostream&))         {    return (*f)(*this); }     // ...     };ostream& endl(ostream& os){     os << '\n'    // nouvelle ligne     os.flush()    // vider le tampon     return *this;}ostream& ends(ostream& os){     os << '\0'    // caractère nul     return *this;}ostream& flush(ostream& os){     os.flush()    // vider le tampon     return *this;}

Les manipulateurs dec, hex et oct agissent sur la classe ios simplement en changeant le bit adéquat dans le champ de forme. Le manipulateur ws agit sur istream également en positionnant le bit adéquat. Il est tout à fait possible de définir ses propres manipulateurs sur ce modèle.

Les manipulateurs avec paramètres sont nettement plus complexes, mais le principe de base est le même. Il faut cependant utiliser une classe intermédiaire dans ce cas. Voici, en simplifiant, une implantation de setw :

class smanip {     ios& (*fn)(ios&, int);     int ag;     public:     smanip(ios& (*f)(ios&, int), int a)         {    fn = f; ag = a; }     friend istream& operator>>(istream& s, smanip&  f)         {    (*f.fn)(s, f.ag); return s; }     friend ostream& operator<<(ostream& s, smanip&  f)         {    (*f.fn)(s, f.ag); return s; }     };ios& setw_fonc(ios& io, int w){     io.width(w);     return io;}smanip setw(int w){     return smanip(setw_fonc, w);}

Le comportement est en fait un peu plus complexe, et de plus le fichier <iomanip.h> est rendu pratiquement illisible par l’emploi de macros et de classes génériques.


Retour au texte.