C++ ohne STL?



  • Ein Prof. meinte neulich zu uns, dass C++ ohne die STL genauso gut für ressourcenschwache Architekturen geeignet ist wie C wenn ein passender Compiler vorhanden ist.

    Wie darf ich das jetzt verstehen - soll ich dann meine eigene String-Klasse aus char* bauen, meine eigenen Container+Speicherverwaltung? Wie ist das dann mit dem FileIO, basiert das nicht auch auf der STL? Muss ich dann meine eigenen Klassen aus den C-Funktionen bauen?



  • warum nicht?
    printf zum bleistift.
    und wozu braucht es die string klasse *g*

    wenns eben wenig platz gibt, muss man sich darauf einstellen.



  • STL-User schrieb:

    Ein Prof. meinte neulich zu uns, dass C++ ohne die STL genauso gut für ressourcenschwache Architekturen geeignet ist wie C wenn ein passender Compiler vorhanden ist.

    Wie darf ich das jetzt verstehen - soll ich dann meine eigene String-Klasse aus char* bauen, meine eigenen Container+Speicherverwaltung? Wie ist das dann mit dem FileIO, basiert das nicht auch auf der STL?

    nu mal langsam. nicht alles der stl frißt gleich wahnsinnig resourcen. aber anderes der standardlib vielleicht noch mehr.
    zur zeit mußte auf std::cout verzichten, weil das ein wenig ungeschickt implemetiert ist und lahmer als printf ist und 100-200k code erzeugt.
    die sachen, die std::string macht, müßtest du auch selber machen, wenn du dynamische zeichenketten brauchst. daß man wo es geht, stringliterale benutzt, muß man sich halt angewöhnen, also nicht gerade

    void log(string const& fileName,string const& line){
       //bitte nicht nachmachen, bloating verdirbt den charakter
       ofstream(fileName.c_str())<<line<<endl;
    }
    ...
    log("log.txt","server started");
    

    andererseits sind die algorithmen nicht schlecht, schneller als std::sort wird dein prof auch nach wochen nicht sein. wenn er ein wenig codesize ausgaben mag für tolle laufzeit, isser hier richtig.

    Muss ich dann meine eigenen Klassen aus den C-Funktionen bauen?

    damit holste einiges raus, wenn du für schwache rechner coden willst, denn die stl ist für normale rechner optimiert. außerdem in ein paar aspekten einfach verschwenderisch. normalerweise dürfte es aber vollauf genügen, auf std::cout zu verzichten und der code sollte schon recht klein sein.



  • @volkard nur mal so aus interesse: was findest du an den iostreams nicht so doll? klar, die handhabung ist nicht unbedingt einfach, aber das es gleich "ungeschickt" implementiert ist?



  • Aus den C Funktionen würde ich nicht meine eigenen Klassen bauen, da diese teilweise auch sehr problematisch sind. Lieber ein solides Design von Grund auf. Aber im Grunde solltest du mal genau angucken was dein Compiler alles bietet und wie die Dinge implementiert sind. Ich würde eher so vorgehen, dass ich die Teile der STL ersetze, die mir nach eingehender Untersuchung zu langsam oder zu fett sind.

    elise schrieb:

    printf zum bleistift.

    printf ist doch eher ein ideales Beispiel dafür, wo die C Library große Macken (auch im Bezug auf Resourcenverschwendung hat) :p

    @otze
    die sind zu `fett`. Schau dir mal an, wie sich die Binary-Größe verhält, wenn du statisch linkst und iostreams benutzt.



  • Wenn sie nicht so fett wären, wären sie aber nicht so flexibel...



  • otze schrieb:

    @volkard nur mal so aus interesse: was findest du an den iostreams nicht so doll? klar, die handhabung ist nicht unbedingt einfach, aber das es gleich "ungeschickt" implementiert ist?

    wozu war noch mal open/close da? mir scheint das einfach ein relikt aus alten tagen, als man noch c-stylish programmieren wollte. und das verändern der puffer zu laufrzeit. die teuren locales. überhaupt total total viele optionen, die alle immer befragt werden müssen. statt cout<<hex<<100 müßte man doch cout<<hex(100) schreiben (keine status-informationen im stream für hex-ausgabe), oder? hat man sich das damals noch nicht vorstellen können?



  • otze schrieb:

    @volkard nur mal so aus interesse: was findest du an den iostreams nicht so doll? klar, die handhabung ist nicht unbedingt einfach, aber das es gleich "ungeschickt" implementiert ist?

    Da muß ich volkard recht geben. Die Iostreams sind sehr schlecht realisiert. Sie sind schlecht designed, langsam und schwer benutzbar.

    Ein Beispiel sind die Modifier. Ein operator<< kann sie verändern ohne sie zurück zu setzen. Die Funktion muß extra Arbeit leisten um dies zu verhindern. Desweiteren sind die Modifier nicht erweiterbar, ich kann keine für meine eigenen Klassen definieren.

    Ein weiterer schwerwiegendes Problem ist die Fehlerbehandlung. Eine Funktion muß ausdrücklich dafür sorgen, dass sie die Streams sich für eine Methode entscheiden. Tut sie dies nicht dann muß sie mit allen Sorten von Fehlerbehandlung fertig werden.

    Ein weiteres Problem ist die Vermischung von Dateien und Strömenen. Wieso zum Teufel soll ein Strom seakbar sein? Nicht alle Ströme sind es, die meisten sogar nicht! Hier wird gegen ein grundlegendes Konzept der Vererbung verstoßen. Eine Basisklasse ist die Schnittmenge der abgeleitenen Klassen und nicht deren Union.

    Desweiteren ist das Puffern Aufgabe der Stromquelle. Dies heißt stream_buf sollt nur ein virtuelle Methoden read und write enthalten. Wenn die Quelle gepuffert werden soll dann ist das die Aufgabe des Implementierers von write und read. Hier schießen die Iostreams über ihre Aufgabe hinaus.

    Dann was bringt die Verbindung von Ein - und Ausgabe? Was ist der Vorteil von foo(iostream&) gegenüber von foo(istream&, ostream&)? Ich sehe nur Nachteile.

    Desweiteren müßten die Eingabefunktionen auch eine Möglichkeit haben den Strom bei einem Formatsfehler in einem ordentlichen Zustand zu belassen. Man kann nicht immer mit einem Zeichen im voraus bestimmen ob eine Eingabe scheitert oder nicht. Darum muß man mehrere Zeichen einlesen. Wenn es nun aber scheitert? Was machen wir mit den eingelesenen Zeichen? Die einzige Möglichkeit wäre sie über putback in den Strom zuück zu schieben. Auch wenn es sehr schwerfällig ist ist es aber der richtige Ansatz nur, dass es nicht hier garantiert ist, dass putback auch funktioniert. putback muß nähmlich nicht eine unbegrenzte Anzahl von Zeichen annehmen. Desweiteren wäre es im Exceptionfall auch nicht sicher da ein new gebraucht werden muß. Dies macht die istreams für kompliziertere Formate nutzlos.

    Desweitern ist es für mich ein Rätzel wie man mit nur Strömen 200kb füllen kann.

    kingruedi schrieb:

    Aus den C Funktionen würde ich nicht meine eigenen Klassen bauen, da diese teilweise auch sehr problematisch sind. Lieber ein solides Design von Grund auf.

    Ich würde aber nicht auf strlen, strcpy, memcopy und memmove verzichten. Die meisten Compiler besitzen masgeschneiderte Optimirungsmethoden für sie.



  • ich mag nicht mehr als "ungeschickt" sagen. und meine größte hochachtung gilt denen, die damals die streams so gegossen haben, wie sie jetzt sind. es war neuland, und das, was sie vollbrachten ist beeindruckend gut für seine zeit. nu hat sich c++ ein wenig gewandelt in richtungen, die absolut nicht vorhersehbar waren, deswegen ein wenig ungeschickt aus heutiger sicht.
    ich beschäftige mich ja mit einer alternativen implemetierung und die zeichen stehen gut, daß ich damit baden gehe, weil meine nicht genug können und dafür nur ein fitzelchen schneller sind. die exe-größe ist kein argument, weil der brocken in ner dll (shared lib) zu liegen hat. und daß es open/close gibt, darf man ja ignorieren, wenn man mag.



  • @Topic: Man kriegt vor allem mit Templates sehr leicht riesige Executables. Ich finde es nicht unbedingt besser, wie bei qsort einen Funktionszeiger zu übergeben, aber es ist platzsparender, als für jedes Vergleichskriterium bei ein und demselben Elementtyp das Template komplett neu zu instanzieren. Auf dieses Problem (wenn es sich als eines erweist) stößt man eben in der STL dauernd.

    ich beschäftige mich ja mit einer alternativen implemetierung und die zeichen stehen gut, daß ich damit baden gehe, weil meine nicht genug können und dafür nur ein fitzelchen schneller sind.

    Wenn du nur das EOF nicht so affig machst wie die iostreams, sind sie schon 10mal besser. Wie war das noch gleich? Es hielt sich lange das Gerücht, dass in Java Streams auf eine Exception enden, ohne dass man es verhindern könne und da wurde ja wahnsinnig drauf geschimpft. Jetzt scheint es eher auf die iostreams zuzutreffen, wenn man die Exceptions anschaltet, aber hier schimpft keiner? Benutzt keiner Exceptions bei I/O-Fehlern? Ich habe mir deine Streams noch nicht angeschaut, aber das EOF interessiert mich jetzt, daher werde ich sie mir mal runterladen. 🙂



  • Ich behaupte mal, dass nen C++ Compiler für so ne Plattform seine eigene kleine "STL" mitbringt die auch auf die Plattform angepasst ist 🙂



  • Optimizer schrieb:

    aber es ist platzsparender, als für jedes Vergleichskriterium bei ein und demselben Elementtyp das Template komplett neu zu instanzieren. Auf dieses Problem (wenn es sich als eines erweist) stößt man eben in der STL dauernd.

    für sort müßte man nen zeiger auf less und einen auf swap übergeben. ungern. die inline-optimierung geht flöten. aber nette idee, einfach mal heap_sort zu nehmen, weils kleineren code macht als intro_sort.

    [quoteWenn du nur das EOF nicht so affig machst wie die iostreams, sind sie schon 10mal besser.[/quote]
    ich denke daran, daß das normalverhalten ist, daß der user while(!eof) read() macht, aber wenn er zu weit liest ne exception fliegt. wie in java.
    aber egal, für was ich mich jetzt entscheide, messungen werden ergeben, daß es doch ganz anders hätte besser gemacht worden sein können wird (synaktisch korrekt?).



  • volkard schrieb:

    ich mag nicht mehr als "ungeschickt" sagen. und meine größte hochachtung gilt denen, die damals die streams so gegossen haben, wie sie jetzt sind. es war neuland, und das, was sie vollbrachten ist beeindruckend gut für seine zeit. nu hat sich c++ ein wenig gewandelt in richtungen, die absolut nicht vorhersehbar waren, deswegen ein wenig ungeschickt aus heutiger sicht.

    Klar war es aus damaliger Sicht eine Meisterleistung allerdings sind sie für heutig Verhältnisse veraltet und müssten ausgetauscht oder stark verbessert werden. Wenn man sich C++ ohne Exceptions und Templates vorstellt dann sind sie gar nicht mal so schlecht. Allerdings ändert das nichts daran, dass man sie überarbeiten muß. Spätestens bei der Standardisirung hätten aber viele der Probleme klar sein müssen. Zu mindest das Problem mit den Exceptions liegt ja auf der Hand von daher sind die heutigen Standard Iostreams aus meiner persöhnlichen Sicht schlecht realisiert. Man hat einfach eine unausgereifte Idee zum Standard erhoben.

    volkard schrieb:

    ich beschäftige mich ja mit einer alternativen implemetierung und die zeichen stehen gut, daß ich damit baden gehe, weil meine nicht genug können und dafür nur ein fitzelchen schneller sind. die exe-größe ist kein argument, weil der brocken in ner dll (shared lib) zu liegen hat. und daß es open/close gibt, darf man ja ignorieren, wenn man mag.

    Ich hab mich auch schon seit einiger Zeit Gedanken über eine Implementirung von Streamklassen gemacht. Hier mal meine Vorschläge. Vielleicht sind ja eine brauchbare Ansätze dabei.

    Modifier würde ich folgendermasen realisieren.

    class Target{
    public:
      virtual uint write(const char*, uint)=0;
    };
    
    class ostream{
    public:
      template<class T>
      ostream&operator<<(const T&t){
        ::write(*this, t);
        return *this;
      }
    private:
      Target*target;
    };
    
    template<class T>
    class hex_modifed_ostream:public T{
    public:
      explicit hex_modified_ostream(ostream&out):
        T(out){}
    
      template<class T>
      hex_modified_ostream&operator<<(const T&t){
        T::opertor<<(t);
        return *this;
      }
    
      ostream&operator<<(int i){
        // hex Implementirung
      }
    private:
      ostream&out;
    };
    
    template<class ostreamT>
    void write(ostreamT&out, int i)
    {
      // dec Implementirung
    }
    
    template<class ostreamT>
    void write(ostreamT&out, char c)
    {
      // ...
    }
    
    //...
    struct Foo
    {
      int a,b;
    };
    
    template<class ostreamT>
    void write(ostreamT&out, const Foo&foo){
      out<<foo.a; 
      hex_modifed_ostream<ostreamT> hex_out(out);
      out<<foo.b;
    }
    // ...
    ostream out;
    foo(out); // einmal dec und einmal hex
    hex_modifed_ostream<ostream> hex_out(out);
    foo(hex_out); // zweimal hex
    

    Ich sehe folgende Vorteile:

    • Neue modifier können nach Lust und Laune definiert und in Kombination mit alten genutzt werden.
    • Eine Ausgabefunktion kann von Außen gesagt bekommen wie etwas zu formatiren ist. Sie kann diese Einstellung benutzen oder sie überschreiben und beim Beenden der Funktion ist die Überschreibung automatisch aufgehoben. Zum Beispiel wäre eine Funktion die ein vector<T> ausgibt doch gehandicapt wenn man T nicht formatieren könnte. Dein cout<<hex(100) Ansatz könnte da Probleme bereiten.

    Folgende Schwachpunkte sehe ich:

    • Compiler muß gut inlinen können sonst kommt es zu Overheat.
    • Alle Ausgabefunktionen sind Templates. Dies dürfte eigentlich kein Problem sein wenn diese Funktion auch wirklich nur für die Ausgabe zuständig ist. Wenn spezielle Formatirung nötig ist (wie zum Beispiel bei int bin => dec) dann kann man auch auf eine Funktion zurückgreifen die ein String zurück gibt und den String ausgeben. Die Formatirungsfunktion muß ja nicht umbedingt ein Template sein.

    Ich hab noch nicht hiermit gearbeitet also könnten es versteckte Probeme geben.

    Bei den Eingabeströmen weiß ich nicht so recht ob es eine gute Idee aber eventuel könnte man die Erkennung der Daten von deren Einlesung trennen. Ich hab schon mehrmals gute Erfahrungen mit der Trennung von Erkennung und Einlesung gemacht.

    Um einen Puffer der die gelesenen Zeichen enthält bis, dass es sicher ist, dass die Eingabe korrekt oder falsch ist kommt man nicht umher.

    istream in;
    if(in.is_at<int>())
      do_bar_stuff(in)
    else if(in.is_at<Foo>())
      do_foo_stuff(in))
    

    Ein Foo anzulegen könnte kostspielig sein und nur um zu testen ob das nächste was der Stream enthält ein Foo ist eines anlegen zu müssen klingt verschwenderisch. Was sich auch als sehr nützlich erwiesen hat war ein was_at.

    template<class T>
    bool istream::was_at(const T&a){
      if(is_at<T>()){
        T b;
        *this>>b;
        if(b == a)
          return true;
        // nutze Puffer zeichen um Einlesen rückgängig zu machen
      }
      return false;
    }
    //...
    vector<int>vec;
    if(in.was_at('{'))
    {
      do{
        int i;
        in>>i;
        vec.push_back(i);
      }while(in.was_at(','));
      if(!in.was_at('}'))
        throw format_error;
    }
    

    Keine Ahnung ob generel Purpose Streams dies brauchen. Ich hab es zu mindest als sehr nützlich empfunden.

    So nun reißt meine Ideen mal in Stücke, damit ich nicht irgendwann über unerwachtete Probleme stolpere. 😉

    Optimizer schrieb:

    @Topic: Man kriegt vor allem mit Templates sehr leicht riesige Executables. Ich finde es nicht unbedingt besser, wie bei qsort einen Funktionszeiger zu übergeben, aber es ist platzsparender, als für jedes Vergleichskriterium bei ein und demselben Elementtyp das Template komplett neu zu instanzieren. Auf dieses Problem (wenn es sich als eines erweist) stößt man eben in der STL dauernd.

    Ja aber in der Prakis wird ja nur basic_ostream<char, char_traits<char> > und basic_istream<char, char_traits<char> > verwendet und meist auch noch durch explicite Instancirung in einer Library. Das ist ja etwas anderes als std::sort wo die Parameter die ganze Zeit wechseln.

    Optimizer schrieb:

    Benutzt keiner Exceptions bei I/O-Fehlern?

    Ich habe nur schlecht Erfahrungen mit ihnen gemacht und ich glaube den meißten wäre es auch zu affig jedesmal für jeden Strom die Ausnahmen einschalten zu müssen.

    Optimizer schrieb:

    Wenn du nur das EOF nicht so affig machst wie die iostreams, sind sie schon 10mal besser.

    Eigentlich finde ich folgendes recht einfach als Test:

    if(in.peek() == EOF)
    

    istream::eof ist affig, da gebe ich dir recht.



  • ich denke an

    template<typename T>
    struct hexer{
    };
    template<>
    struct hexer<unsigned int>{
      unsigned int& hexedVictim;
      hex(unsigned int& hv):
      hexedVictim(hv){
      }
      friend ostream& operator<<(ostream& out,hex const& h){
         unsigned int x=h.hexedVictim;
         do
            out<<"0123456789abcdef"[x%16];
         while(x/=16);
      }
    };
    template<typename T>
    hexer<T> hex(T& t){
       return hexer<T>(t);
    }
    

    also sehr direkte handles auf die zu hexenden daten. und sachen, die nicht gehext werden können, müssen halt compilerfehler liefern. also hex war keine funktion, die etwa einen string zurücklifert, auch wenn es den anschein hat, wenn man den vorugen code so liest.

    Ben04 schrieb:

    Um einen Puffer der die gelesenen Zeichen enthält bis, dass es sicher ist, dass die Eingabe korrekt oder falsch ist kommt man nicht umher.

    man muß aber darum umher kommen. immerhin kann das gerade zu lesende objekt ein sound-sample von 30M länge sein.

    können die dateiformate nicht so sein, daß man weiß, was für ein typ danach kommt?



  • Ben04 schrieb:

    Ein Foo anzulegen könnte kostspielig sein und nur um zu testen ob das nächste was der Stream enthält ein Foo ist eines anlegen zu müssen klingt verschwenderisch. Was sich auch als sehr nützlich erwiesen hat war ein was_at.

    ich hab allerbeste erfahrungen mit

    Foo::Foo(istream& in)
    :Base1(in),
    Base2(in),
    member1(in),
    member2(in)
    {
    }
    

    es ist einfach nur schweineschnell. und einfach. und mir ausreichend wartbar. und die factory liest einfach immer die klassenkenzeichnung vor dem objekt und ruft den entsprechenden new auf. die virtual void writeAt schreibt vor die nutzdaten die klassenkennzeichnung. da kann xml mal ganz schön nach hause gehen. um's dem menschen noch ein wenig netter in den files zu machen, hab ich noch nach der klassenkenzeichnung "{\n" und nach den nutzdaten "}\n\n" geschrieben. geschrieben wurde ascii und zahlen hex (für speed). menschen können zwar drin rumändern, aber perl-scrips machen das noch besser.

    Eigentlich finde ich folgendes recht einfach als Test:

    if(in.peek() == EOF)
    

    istream::eof ist affig, da gebe ich dir recht.

    äh. peek() liefert nen char, alles ander wäre unfug, oder? da passt EOF nicht rein.



  • volkard schrieb:

    Ben04 schrieb:

    Ein Foo anzulegen könnte kostspielig sein und nur um zu testen ob das nächste was der Stream enthält ein Foo ist eines anlegen zu müssen klingt verschwenderisch. Was sich auch als sehr nützlich erwiesen hat war ein was_at.

    ich hab allerbeste erfahrungen mit

    Foo::Foo(istream& in)
    :Base1(in),
    Base2(in),
    member1(in),
    member2(in)
    {
    }
    

    es ist einfach nur schweineschnell. und einfach. und mir ausreichend wartbar. und die factory liest einfach immer die klassenkenzeichnung vor dem objekt und ruft den entsprechenden new auf. die virtual void writeAt schreibt vor die nutzdaten die klassenkennzeichnung. da kann xml mal ganz schön nach hause gehen. um's dem menschen noch ein wenig netter in den files zu machen, hab ich noch nach der klassenkenzeichnung "{\n" und nach den nutzdaten "}\n\n" geschrieben. geschrieben wurde ascii und zahlen hex (für speed). menschen können zwar drin rumändern, aber perl-scrips machen das noch besser.

    Klar ist das schweine schnelaber nur bedingt vom Menschen lesbar. So wie ich es sehe kommt ein Container nicht umher die Zahl der Elemente als erstes abzuspeichern (oder irre ich da?). Der User sieht dann 3 {1 5 6} fügt mal schnell ein Element hinzu und du hast 3 {1 5 6 7} und das wäre ein Problem. XML ist ja nicht so sehr für Schnelligkeit ausgelegt, eher für leichte Veränderbarkeit vom Menschen mit Notpad. Meiner Meinung nach vergleichst du 2 verschiedene Paar Schuhe.

    volkard schrieb:

    Eigentlich finde ich folgendes recht einfach als Test:

    if(in.peek() == EOF)
    

    istream::eof ist affig, da gebe ich dir recht.

    äh. peek() liefert nen char, alles ander wäre unfug, oder? da passt EOF nicht rein.

    peek() liefert aus genau diesem Grund ein int zurück.
    http://www.cppreference.com/cppio/peek.html



  • Hallo,
    wie gefallen euch eigentlich die boost::iostreams?

    http://www.boost.org/libs/iostreams/doc/index.html

    Mein erster Eindruck ist durchaus positiv (Filtering-Streams z.B. fand ich schon immer sehr nützlich). Hab' mich aber noch nicht intensiv genug damit beschäftigt um die Streams wirklich beurteilen zu können.



  • Ben04 schrieb:

    So wie ich es sehe kommt ein Container nicht umher die Zahl der Elemente als erstes abzuspeichern (oder irre ich da?). Der User sieht dann 3 {1 5 6} fügt mal schnell ein Element hinzu und du hast 3 {1 5 6 7} und das wäre ein Problem.

    jup.
    deswegen hatte ich da gemogelt und {1 5 6 7} nur gemacht und es war noch ok, weil containers selten sind. schlimm sind natürlich strings ohne die längenangabe am anfang.
    ich dachte an zwei sorten streams, plainstreams und binarystreams, normalerweise werden binarystreams verwendet, aber der user kann jederzeit die welt auch auf nen plainstream speichern oder von da laden. naja, als zukonftsvision. war so aber auch schon ok und ich hab statt 10 min (konkurrenz) nur 20 sec gebraucht für 30M strukturierte daten. hab das projekt aber nicht fortgeführt.



  • elise schrieb:

    warum nicht?
    printf zum bleistift.
    und wozu braucht es die string klasse *g*

    Hm, string meide ich irgendwie und bastel immer spezialisierte Alternativen (die wahrscheinlich viel schlechter sind, aber egal 😉 ). Ich denke die Stream-Klassen braucht man, sonst modelliert man sich seine Container eben selbst 😉



  • HumeSikkins schrieb:

    Hallo,
    wie gefallen euch eigentlich die boost::iostreams?

    http://www.boost.org/libs/iostreams/doc/index.html

    Mein erster Eindruck ist durchaus positiv (Filtering-Streams z.B. fand ich schon immer sehr nützlich). Hab' mich aber noch nicht intensiv genug damit beschäftigt um die Streams wirklich beurteilen zu können.

    Sieht cool aus. So ein bzip2- oder Regex-Filter kann schon praktisch sein und es ist schön, solche feinen Dinge in einer zusammenhängenden Bibliothek vorzufinden. Aus boost ist ganz schön was geworden.



  • volkard schrieb:

    ich dachte an zwei sorten streams, plainstreams und binarystreams, normalerweise werden binarystreams verwendet, aber der user kann jederzeit die welt auch auf nen plainstream speichern oder von da laden. naja, als zukonftsvision. war so aber auch schon ok und ich hab statt 10 min (konkurrenz) nur 20 sec gebraucht für 30M strukturierte daten. hab das projekt aber nicht fortgeführt.

    Du hast aber dafür die Eigenschaft geopfert, dass die Daten ohne weiteres vom Menschen lesbar sind. Die Idee 2 austauschbare Streamsorten zu benutzen hatte ich auch schon hab sie aber verworfen da beispielsweise XML nict bloß anders formatiert ist, sondern auch noch Metadaten benötigt.

    <a>
      <b>8</b>
      <c>12</c>
    </a>
    

    Eigentlich nur mit Metadaten sinnvoll.

    <Geburtstag>
      <Tag>8</Tag>
      <Monat>12</Monat>
    </Geburtstag>
    

    Zum generiren von XML braucht es also mehr Informationen als für binäre Representationen. Dann gibt es noch ein weiters Problem dies wäre auch gültiges XML

    <Geburtstag>
      <Monat>12</Monat>
      <Tag>8</Tag>
    </Geburtstag>
    

    Dies würde aber Probleme bereiten da die binären Streams mit Hilfe der Reihenfolge die Daten deuten.

    Meiner Meinung nach kann man nur die Zeichenquelle und Ausgabe teilen.

    @HumeSikkins Ich finde, dass es die IOStreams um sehr nützliche Funktionen erweitert. Diese auch gut umsetzt aber leider die alten Probleme nicht löst.


Anmelden zum Antworten