Je voudrais exposer certains objets sous forme de récipients abstraits avec des possibilités de manipulation de style stl (pour les boucles de protection, itérateurs) et masquer les détails de la mise en œuvre du conteneur. P>
Les problèmes de performance ne comptent pas (appels virtuels et même une allocation de mémoire lors de la copie «Universal» Itérateur sont acceptables). P>
Je vais écrire une interface de conteneur abstrait avec des fonctions virtuelles pures (+ "universel" itérateur sur le conteneur) et un adaptateur d'implémentation pour les conteneurs séquentiels STL. P>
Mais peut-être que des bibliothèques existantes sont utiles à cet effet? P>
ou c'est totalement une mauvaise idée? P>
5 Réponses :
Si vos "objets" ne sont pas des objets stl mais ceux personnalisés, je pense que c'est une bonne idée.
Comme vous pouvez le voir sur http://www.sgi.com/tech/stl/vector.html , vecteur" est un modèle de "RandomAccessContainer. La plupart des packages de boost utilisent des concepts similaires (le terme réellement est "concept") p>
en C ++, vous avez deux possibilités de faire ceci: p>
avec des modèles que vous pouvez faire quelque chose comme: p>
Mes objets peuvent être ou ne peuvent pas être des objets STL, je souhaite cacher ce fait à la compilation du code du client pour fournir la liberté de modifier le conteneur de mise en œuvre sans forcer le code client à recompiler. Je voudrais donc obtenir une classe abstraite (interface) qui est un modèle de RandomAccessContainer et un adaptateur de mise en œuvre pour un conteneur particulier (STL possible possible) qui implémente une telle interface
Voici mon avenir wrapper itérateur pour le style Java implémenté un. C'est moche. Les pièces de boost sont facultatives une pourraient être refactées. P>
La solution la plus générique au problème de "Exposer une classe C ++ de telle manière que les utilisateurs de la classe ne doivent pas nécessairement recompiler leurs programmes chaque fois que ma mise en œuvre de la classe change" est le modèle PIMPL. Pour plus d'informations: http://en.wikipedia.org/wiki/opaque_pointer p>
Les itérateurs C ++ sont copieux. Les pointeurs ne fournissent pas la sémantique nécessaire pour cela. Notez également que le type d'itérateur concret est inconnu un code utilisateur. Cela rend pimplacplicable pimplacplicable ici.
Vous devez juste 1. envelopper vos itérateurs de la même manière (YEP, également à l'aide de PIMPL), 2. Implémentez votre opération de copie non-triviale (bien qu'elle soit plutôt triviale dans sa non-provisoire).
Je comprends complètement la question de l'utilisateur. Il / elle veut une classe de conteneurs personnalisée qui expose à l'utilisateur une interface de type STL. Les conteneurs STL standard ne suffisent pas d'une certaine manière et ils ne sont donc pas un choix approprié.
Par exemple, j'ai une classe d'interface pour une «Dataline» appelée idataline. Une implémentation de l'interface IDataline prend à la construction d'une chaîne délimitée, analyse et expose la liste des champs. Via un const_iterator avec la sémantique Forward_iterator_Tag. Aucun conteneur STL ne peut le faire hors de la boîte. P>
En outre, ma classe client souhaite pouvoir parcourir deux champs de lignes de données et les comparer, le champ par champ. p>
J'ai défini l'interface IDataline comme suit: p> Le problème est vu sur les lignes 11, 18 et 19 - Nous devons pouvoir être capables de Renvoyer un const_itéator, qui nécessite un constructeur de copie, mais comme il est virtuel, il n'y a ni de par défaut ni un constructeur de copie (pour le type d'interface) et le compilateur (correctement). P> Vous pourriez argumenter que Je pourrais définir le début () et la fin () comme: p> alors, je peux créer deux instances de l'itérateur spécialisé dans l'hôte spécialisé et renvoyer des références (ou des pointeurs pour ceux-ci qui préfèrent ceux-ci), pour que cela fonctionne pour travailler pour mon cas. p> Le problème est qu'une telle mise en œuvre ne répond pas à toutes les exigences des itérateurs transfrontaliers et se cassera dans des cas d'utilisation plus générale qui s'appuient sur l'itérateur à terme Sémantique. P> Il y a deux façons que j'ai trouvé après un peu de pensée (et de collègue consultez) que cela peut être adressé: p> Votre classe hôte doit-elle être Eduardo Leon strong> ci-dessus indique que l'itérateur lui-même peut être enveloppé à l'aide du pimpl (pointeur à une implémentation) idiome. Bien qu'il y ait beaucoup de matériel disponible qui décrit minutieusement cette technique,
Thomas Becker a quelques conseils utiles (type Erasure) . Vous pouvez également trouver papier effrayant de Stroustrup utile. P>
+1 Pour le type de mention Erasure et le travail de Becker - Any_berator est probablement la solution parfaite ici. Aucune idée de la raison pour laquelle vous mentionnez Ecary Tho, je pensais que c'était principalement sur la suppression de la dépendance des allocator à partir d'itérateurs (qui n'a rien à voir avec des interfaces génériques, mais mettant en œuvre l'itérateur sur le même «niveau» que le conteneur et non comme une classe imbriquée IIRC ).
Scary, bien sûr, est un détail de mise en œuvre et, comme vous l'avez dit, c'est orthogonal. J'ai ajouté que la peine plus tard, lorsque je me suis rendu compte, cela pourrait potentiellement mettre en œuvre et expérimenter les nouveaux itérateurs un peu plus agréable.
Quel serait l'avantage gagné que vous ne pouviez pas mettre en œuvre avec des conteneurs STL sous-jacents? En C ++ 0x, le mot clé code> code> peut être utilisé pour impliquer le type d'itérateur correct pour un conteneur par la rvalue i> mais cela peut ne pas suffire à vos besoins.
Pourquoi voulez-vous faire cela? Les conteneurs STL font des tâches différentes avec une garantie de performance différente, si vous ne vous dérangeez pas de performance, vous ne devez pas créer un "conteneur universel", mais utilisez simplement std :: vecteur.
@ AJG85, @ Alessandro Teruzzi: Je ne veux pas recompiler le code "Client" lorsque l'implémentation décide de modifier le conteneur (par exemple) de Vector à Deque. Stl utilisé ici comme standard connu pour la manipulation des conteneurs, pas pour des performances maximales
Votre tentative d'écrire un conteneur Pimp. Scott Myers a une discussion sur cela dans l'un de ses livres. Même si les conteneurs sont très génériques en raison de la mise en œuvre sous-jacente, elles ne sont pas simplement coupées / coller remplaçables. c'est à dire. Vous ne pouvez pas remplacer un vecteur avec une carte sans travailler supplémentaire.
@user STL est en fait connu pour la performance. Vous avez peut-être besoin d'une interface commune entre la mise en œuvre du client et du serveur pour découpler des changements de backend du client avant?
@ AJG85 Oui, j'ai besoin d'une interface commune. Mais je suppose que cela est pratique pour l'utilisateur d'avoir une interface qui peut être utilisée avec des motifs bien connus communs ou des algorithmes stl simples comme pour
@Martin: Semble que vous êtes une rigidité, il y a des problèmes pour généraliser tous les conteneurs STL. Cependant, j'ai moins d'ambias pour généraliser au moins des conteneurs séquentiels à l'esprit (vecteur. Klist, déséquilibre) avec une simple possibilité d'itération
+1 Pour une question qui me dérange depuis longtemps. Je veux aussi avoir le pouvoir des itérateurs de style Java aussi. J'ai enveloppé une décision de conception Java dans l'itérateur classique C ++ à l'aide de la technique de clone et de Pimpl idiom, mais cela semble laid.
Juste un peu de note: une fois que vous avez obtenu les itérateurs généralisés, vous pouvez utiliser des gammes simples (comme Boost's iTerator_Range) pour vous envelopper des conteneurs uniformément.