Quelles sont les utilisations pratiques de la " Patron de modèle curieusement récurrent " ? Le " classe comptée "L'exemple couramment montré n'est pas un exemple convaincant pour moi.
Réponses
Trop de publicités?Liaison dynamique simulée . Éviter le coût des appels de fonctions virtuelles tout en conservant certains des avantages hiérarchiques est une victoire énorme pour les sous-systèmes où cela peut être fait dans le projet sur lequel je travaille actuellement.
Il est aussi particulièrement utile pour mixins (j'entends par là les classes dont vous héritez pour fournir des fonctionnalités) qui doivent elles-mêmes savoir sur quel type elles opèrent (et doivent donc être des modèles).
En C++ efficace Scott Meyers fournit comme exemple un modèle de classe NewHandlerSupport<T>. Il contient une méthode statique permettant de surcharger le gestionnaire de nouveau pour une classe particulière (de la même manière que std::set_new_handler le fait pour l'opérateur new par défaut), et un opérateur new qui utilise le gestionnaire. Afin de fournir un gestionnaire par type, la classe parente doit savoir sur quel type il agit, donc il doit être un modèle de classe. Le paramètre du modèle est la classe enfant.
Vous ne pourriez pas vraiment le faire sans CRTP, puisque vous avez besoin que le modèle NewHandlerSupport soit instancié séparément, avec un membre de données statique distinct pour stocker le new_handler actuel, par classe qui l'utilise.
Il est évident que l'ensemble de cet exemple n'est pas du tout sécurisé par les threads, mais il illustre bien le propos.
Meyers suggère que CRTP pourrait être considéré comme "Do It For Me". Je dirais que c'est généralement le cas pour tout mixin, et que 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 l'on considère que le type de la sous-classe qui est transmis à la superclasse n'est nécessaire qu'au moment de l'expansion de la méthode. Ainsi, tous les types sont définis. Vous avez juste besoin du motif pour importer le type symbolique de la sous-classe dans la superclasse, mais il s'agit simplement d'une déclaration en avant - comme le sont par définition tous les types param formels des modèles - en ce qui concerne la superclasse.
Nous utilisons sous une forme quelque peu modifiée, en passant la sous-classe dans une structure de type traits à la super-classe pour permettre à la super-classe de retourner des objets du type dérivé. L'application est une bibliothèque pour le calcul géométrique (points, vecteurs, lignes, boîtes) où toute la fonctionnalité générique est implémentée dans la superclasse, et la sous-classe définit juste un type spécifique : CFltPoint hérite de TGenPoint. De plus, CFltPoint existait avant TGenPoint, donc la sous-classe était un moyen naturel de remanier le système.
Généralement, il est utilisé pour les patrons de type polymorphique où il n'est pas nécessaire de pouvoir choisir la classe dérivée au moment de l'exécution, mais seulement au moment de la compilation. Cela permet d'économiser la surcharge de l'appel de la fonction virtuelle au moment de l'exécution.