Question

Quelles sont certaines utilisations pratiques du " modèle de modèle curieusement récurrent " ;? La " classe comptée " exemple communément montré n'est tout simplement pas un exemple convaincant pour moi.

Était-ce utile?

La solution

liaison dynamique simulée . Éviter le coût des appels de fonctions virtuelles tout en conservant certains des avantages hiérarchiques est un gain énorme pour les sous-systèmes sur lesquels cela peut être fait dans le projet sur lequel je travaille actuellement.

Autres conseils

Cela est également particulièrement utile pour les mixins (par lesquelles je veux dire les classes dont vous héritez pour fournir des fonctionnalités) qui ont elles-mêmes besoin de savoir le type sur lequel elles fonctionnent (et doivent donc être des modèles).

Dans Effective C ++ , Scott Meyers fournit un exemple de modèle de classe NewHandlerSupport < T > ;. Cela contient une méthode statique pour remplacer le nouveau gestionnaire pour une classe particulière (de la même manière que std :: set_new_handler pour l'opérateur par défaut new) et un opérateur new qui utilise le gestionnaire. Afin de fournir un gestionnaire par type, la classe parente doit savoir sur quel type elle agit, elle doit donc être un modèle de classe. Le paramètre template est la classe enfant.

Vous ne pouvez pas vraiment faire cela sans CRTP, car vous avez besoin que le modèle NewHandlerSupport soit instancié séparément, avec un membre de données statique séparé pour stocker le new_handler actuel, par classe qui l'utilise.

Évidemment, l'exemple dans son ensemble est extrêmement non thread-safe, mais il illustre bien ce point.

Meyers suggère que le CRTP pourrait être considéré comme un "Do It For Me". Je dirais que c'est généralement le cas pour n'importe quel mixin, et CRTP s'applique dans le cas où vous avez besoin d'un modèle de mixin plutôt que d'une simple classe de mixin.

Le CRTP devient beaucoup moins curieux si vous considérez que le type de sous-classe transmis à la super-classe n’est nécessaire que lors du développement de la méthode. Tous les types sont définis. Vous avez juste besoin du motif pour importer le type de sous-classe symbolique dans la superclasse, mais il ne s'agit que d'une déclaration forward - comme tous les types de paramètres de modèle formels le sont par définition - en ce qui concerne la superclasse.

Nous utilisons une forme quelque peu modifiée, en passant la sous-classe d'une structure de type traits à la super-classe pour permettre à la super-classe de renvoyer des objets du type dérivé. L'application est une bibliothèque pour le calcul géométrique (points, vecteurs, lignes, boîtes) dans laquelle toutes les fonctionnalités génériques sont implémentées dans la superclasse, et la sous-classe définit simplement un type spécifique: CFltPoint hérite de TGenPoint. De plus, CFltPoint existait avant TGenPoint, le sous-classement était donc un moyen naturel de le refactoriser.

En règle générale, il est utilisé pour les modèles de type polymorphique pour lesquels vous n'avez pas besoin de pouvoir choisir la classe dérivée au moment de l'exécution, mais au moment de la compilation. Cela peut économiser la surcharge de l'appel de fonction virtuelle au moment de l'exécution.

Pour une utilisation réelle du CRTP dans les bibliothèques, consultez ATL et WTL (wtl.sf.net). Il est largement utilisé là-bas pour le polymorphisme au moment de la compilation.

Cela ressemble un peu à une macro C: profitez du fait que la macro n’est pas compilée au moment de la définition, mais au moment de son utilisation.

#define CALL_THE_RIGHT_FOO foo()

fichier A:

static void foo() {
   // do file A thing
}
...
CALL_THE_RIGHT_FOO
...

fichier A:

static void foo() {
   // do file B thing
}
...
CALL_THE_RIGHT_FOO
...

Le modèle d'utilisation du modèle que vous décrivez nous permet d’appeler "le bon truc" " dans le modèle parent, reporter la définition de ce qu'est exactement le bon foo jusqu'à ce que le modèle soit instancié. Sauf dans ce cas, c'est la distinction entre ClassA :: foo et ClassB :: foo basée sur la valeur de T dans Parent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top