11
votes

Pourquoi Ostream_iterator doit-il déclarer expliquer explicitement le type d'objets à la sortie?

Dans Current C ++, la classe Ostream_iterator a été conçue comme suit: xxx pré>

pour moi, cette conception est sous-optimale. Parce que l'utilisateur doit spécifier le type T lors de la déclaration d'un ostream_iterator comme ceci: ostream_iterator oi (COUT); code> En fait, COUT peut prendre tout type d'objet comme argument, plutôt qu'un seul type . C'est une restriction évidente. P> xxx pré>

maintenant, nous pouvons l'utiliser comme suit: P>

ostream_iterator<int> oi(cout);


15 commentaires

Quel est le valeur_type de votre ostream_iterator?


@Msalters: Il n'est pas nécessaire que la classe Ostream_iterator doit typée une valeur de valeur imbriquée. Je pense donc que la déduction du type peut être retardée jusqu'à ce que l'opérateur = () soit appelé.


Pehaps Je ne comprends pas le problème que vous essayez de résoudre. Quels algorithmes allez-vous utiliser avec votre ostream_iterator qui allez générer des objets de différents types? Si vous diffusez des objets de différents types, comment seriez-vous alors capable de connaître les types corrects pour les lire?


@Chals Bailey: Il y a beaucoup d'astuces pour dire à l'extracteur quel est le type d'objet suivant. Par exemple, vous pouvez utiliser un entier comme identifiant de type pour indiquer le type d'objet suivant.


Nous n'avons pas besoin de veiller à ce que l'extracteur lira les objets du flux. Tout comme vous écrivez cout << 1 << "Bonjour"; Vous ne vous souciez pas de la façon dont l'extracteur lira son contenu.


@XMLLLMX, mais quel est le point de que lorsque vous êtes itération sur le contenu d'un conteneur où chaque entrée est de type t ? d'ailleurs. Ceci est pour sortie pas pour extraire d'un ruisseau ...


Je pense que vous feriez mieux d'illustrer le point que j'essaie de faire. Si vous avez passé votre itérateur à un algorithme, cela ne donnera pas à l'occasion d'arrêter et de mettre votre identifiant. Si vous avez besoin d'un contrôle de grain plus fin et construisez l'objet de sortie à la fois, pourquoi pas simplement utiliser un std :: ostream & qui a déjà une sortie polymorphe idiom: opérateur <<< / code >?


& NIM: Vous avez raison. Je suis hors sujet.


@Chals Bailey: Nous discutons de la conception d'Ostream_iterator plutôt que de la utiliser. Je pense que ce dernier est plus générique et plus élégant que le design actuel. Imaginez que nous avons un algorithme pour générer plusieurs types d'objets à l'ostream, la discussion aurait un sens.


Que croyez-vous que l'objectif de conception de ostream_iterator est ou devrait être? Parce que je crois que vous essayez de résoudre un problème différent de la classe des problèmes que la standard résoue.


@xmllmx, qui nécessiterait un conteneur capable de maintenir plusieurs types non liés (dont aucun du conteneur STL n'est capable de - à moins que je n'ai pas manqué un tour quelque part ...) Le seul conteneur que je pouvais penser qui peut contenir plusieurs Types est un Boost Boost :: Fusion Séquence, mais à nouveau là, vous sortez directement au flux et profitez de l'opérateur <<< / code>


@Nim: Utilisez cette dernière version ne cassera pas les conteneurs et algorithmes standard existants, il fonctionnera dans tous les cas que la version actuelle fonctionne. Mais ce dernier est plus beau pour moi.


@NIM: Cela ne nécessiterait pas de conteneur capable de maintenir plusieurs types non liés. Cela supporterait un conteneur capable de tenir plusieurs types non liés.


@Msalters: le valeur_type est void (c'est un itérateur de sortie, 24.3.1 / 1)


Op est correct. J'attends make_ostream_joininer à partir de 2020.


4 Réponses :


0
votes

Oui, vous avez raison. Il serait plus flexible que vous le suggérez. Cependant, la manière dont il est conçu correspond de plus près à la manière dont STL utilise des itérateurs: un type itérateur pour le type de données (T).


0 commentaires

1
votes

Je pense que la raison est que cela a également d'autres membres. Évidemment, l'ensemble des fonctions membres doit être cohérent dans leur comportement pour un ensemble donné de T et d'autres arguments de modèle.

Un danger dans Opérateur << / Code> Être instancié pour un ensemble d'arguments de modèle différés de ce qui est utilisé pour instancier opérateur * ou opérateur ++

Par conséquent, les méthodes individuelles ne sont pas des modèles eux-mêmes et plutôt la totalité de la classe est un modèle, assurez-vous donc un uniforme T et d'autres arguments de modèle.


0 commentaires

1
votes

Il semble que vous puissiez avoir raison.

Voyons si nous pouvons construire un ostream_iterator qui n'a pas besoin d'un argument de modèle. p>

L'itérateur fonctionne en copiant des valeurs, donc * iter = x; ++ iter; code> L'itérateur triche en faisant de l'opérateur * Retourner lui-même et ++ iter code> se revenant également sans changer d'état. La "magie" est dans l'opérateur = qui effectue la sortie. P>

Le "COUT" doit être un membre de classe de type Otstream *. Il faut être un pointeur car les itérateurs doivent être assignables, nous attribuons ainsi le membre (appeler os os) à l'adresse du flux passé. P>

donc nous surcharger l'opérateur = P >

typedef our_basic_ostream_iterator<char> our_ostream_iterator;
typedef our_basic_ostream_iterator<wchar_t> our_wostream_iterator;


5 commentaires

Cela doit toujours être utilisé comme notre_ostream_iterator , ce qui est ce que le questionneur veut éviter. Pour avoir une chance de l'utiliser sans nommer son type, vous avez également besoin d'une sorte de fonction d'emballage qui déduira les arguments de modèle (puis plus C ++ 0x auto et déclinger signifie que vous n'avez jamais besoin d'utiliser le type, tandis que dans C ++ 03, vous avez parfois besoin de l'épeler).


Je ne sais pas si l'OP doit déduire le type d'élément et l'entrée / sortie large du constructeur, mais vous pouvez utiliser une fonction pour déduire quel type pour faire et utiliser cela, dépendant de ce que vous avez passé.


Vous passez stream_type s par valeur et enregistrez son adresse dans os .


Cette réponse prétend "construire un ostream_itéator qui n'a pas besoin d'un argument de modèle.", Mais a clairement typename e dans sa définition de notre_basic_ostream_iterator . Comment est-ce correct?


Op signifiait que le type étant diffusé. Le paramètre de modèle dans mon code est celui du type d'élément c'est-à-dire, qu'il s'agisse de char ou de wchar_t et que vous puissiez TAPEDEF IT, car vous le pouvez maintenant. Le type de caractère peut bien être dérivable de l'objet de flux que vous pouvez utiliser automatiquement make_ostream_iterator (...),



3
votes

La réponse simple est que itérateur code> a des types associés et ostream_iterator code> viole conceptuellement le concept d'un itérateur en exigeant un valeur_type code> même quand il est pas nécessaire. (C'est fondamentalement la réponse @ pts)

Ce que vous proposez est lié à l'idée derrière les nouveaux "opérateurs transparents", tels que le nouveau std :: plus code>. Qui consistent à avoir une instanciation spéciale dont la fonction membre a une déduction de type retardée. P>

Il est également compatible en arrière, car void code> n'est pas une instanciation utile pour commencer. De plus, le paramètre void code> est également la valeur par défaut. Par exemple, Modèle STRIT STD :: plus {...} code> est la nouvelle déclaration. p>


une mise en œuvre possible d'un ostream transparent code> fort> p>

revenir de std :: ostream_iterator Code>, un test important est de savoir si nous voulons le faire fonctionner avec std :: copier code> comme std :: ostream_iterator code> est généralement utilisé: p>

std::send(e.begin(), e.end(), std::cout, ", ");


0 commentaires