6
votes

pimpl-idiome dans le modèle; quel pointeur intelligent?

J'utilise habituellement un boost :: scoped_ptr pour Pimpl's (pour une raison pour une raison parce que je ne reçois pas de surprises si j'oublie de traiter le constructeur de copie)

avec des modèles, mais je ne peux pas simplement mettre le destructeur dans Le fichier CPP où l'IPL est entièrement défini afin de répondre aux exigences du destructeur de Scoped_Ptr. Cela fonctionne de toute façon mais je ne suis pas sûr de bien vouloir travailler ou juste par hasard. Y a-t-il des «meilleures pratiques» ou de la norme? Scoped_ptr est-il le meilleur pointeur intelligent pour PIMPLS dans des classes non copieuses? xxx


6 commentaires

Ce type de mise en œuvre PIMPL n'a aucun sens car afin d'instantiier le modèle C, vous devez savoir que le type T. pimpl, d'autre part, cache entièrement un équivalent de T de l'utilisateur.


@Vladlazarenko hmm, j'ai pensé Boost boost :: Scoped_Ptr travaille aussi bien sur des classes prédéclarées. Dans ce cas, cela dépend si T est défini ou prédeclamé. L'instance de ce scoped_ptr serait cachée dans la mise en œuvre (pimpl_ (nouveau t ()).


@DAVIDFEURLE: Pas vraiment, pour que ce modèle fonctionne, la taille de t , ainsi que son interface, doit être exposée, car des "clients" doivent instancier le modèle. Par exemple, où appelez-vous nouveau t () ? Vous ne pouvez pas masquer cela dans le fichier "CPP" car il doit être dans le modèle. Donc ce n'est pas pimpl.


@Vlad Lazarenko Bon point. Je vois où j'ai commis mon erreur et pourquoi ça marche


Donc, on dirait dans ce cas depuis que je dois définir de toute façon t de toute façon, je dois simplement en faire un membre privé pour économiser des coûts.


PIMPL est utilisé pour masquer les détails d'une classe donnée. Quels détails de classe voulez-vous cacher ici?


3 Réponses :



1
votes

boost :: partagé_ptr ne nécessite pas une définition complète autre que le point d'instanciation - dans le constructeur, dans le cas d'un pimpl. boost :: partagé_ptr est pas approprié pour l'idiome pimpl, Cependant, puisqu'il donne une sémantique très inattendue (sémantique de référence pour l'affectation ou la copie); Si vous voulez vraiment la complexité supplémentaire d'un pointeur intelligent, boost :: scoped_ptr serait plus approprié (mais il nécessite une définition complète au point que son destructeur est instancié).

En ce qui concerne les modèles, cela n'a aucun sens d'utiliser l'idiome pimpl pour les détails de la mise en œuvre de l'en-tête. Dans l'absence de exportation , Tous les détails de la mise en œuvre d'un modèle de classe doivent être inclus partout le modèle est utilisé, alors la motivation derrière le pimpl idiome cesse d'exister.


0 commentaires

2
votes

Deux ans plus tard, je comprends bien la situation beaucoup mieux, dans l'intérêt de garder la pile Dépassement des réponses pertinentes et à jour ici est de savoir comment je répondrais aujourd'hui à la question.

Le principe de ma question initiale est quelque peu défectueux. La raison d'utiliser le pimpl-idiom consiste à masquer les détails de la mise en œuvre du compilateur. Cela se fait en stockant la mise en œuvre via un pointeur opaque (pointeur à un type de données déclaré mais non défini). Cela peut réduire considérablement la quantité d'en-têtes nécessaires par d'autres unités de compilation qui interagissent avec la classe et accélèrent ainsi l'heure de compilation. Dans le cas du modèle de ma question, il est nécessaire que le type t soit parfaitement connu au point d'instanciation qui, en pratique, nécessite que le type de l'implémentation soit complètement défini dans la mesure où C est utilisé. Cela n'est clairement pas un exemple du pimpl-idiome dans le sens classique du terme.

Il existe d'autres raisons de contenir des données de classes via un pointeur privé, par exemple, il permet une mise en œuvre facile du déplacement et de l'échange sans jeton et est également bon si votre classe doit remplir une garantie d'exception forte (voir copie et échange idiom Quel est l'idiome de copie-and-swap? ). D'autre part, il ajoute une couche d'indirection (entraînant souvent une cache Mlle) sur tous les accès à l'IPL et à une allocation de tas / distribution de la transaction à la création et à la destruction de l'IPL. Celles-ci peuvent être des pénalités de performance substantielles, cette solution ne devrait donc pas être considérée comme une balle d'argent.

Si vous pouvez utiliser c ++ 11, STD :: unique_ptr doit être utilisé à la place de boost :: scoped_ptr.


0 commentaires