wofür templates?



  • [ Dieser Beitrag wurde am 03.06.2003 um 11:27 Uhr von TS++ editiert. ]



  • Auch interessant ist sowas:

    template<int i, int j> struct max {
      enum { ret = i > j ? i : j };
    };
    template<int i, int j, int k> struct max3 {
      enum { ret = max<max<i, j>::ret, k>::ret };
    };
    
    template<class T, int i> class fixed_vector {
      T p[i];
    public:
      T &operator[](int x) { return p[x]; }
      T operator[] (int x) const { return p[x]; }
    }
    
    struct X {
      enum _type { Int, Double, Fixed_vector } type;
      union {
        int *a;
        double *b;
        fixed_vector<int, 4> *c;
      } x;
      char z[max3<sizeof(int), sizeof(double), sizeof(fixed_vector<int, 4> )>::ret];
      X(_type x) : type(x) {
        switch (x) {
        case Int:
           x.a = z;
           new(a) int;
           break;
        case Double:
           x.b = z;
           new(b) double;
           break;
        case Fixed_vector:
           x.c = z;
           new(c) fixed_vector<int, 4>;
           break;
        }
      }
      ~X() {
        if (type == Fixed_vector)
          x.c->~fixed_vector();
      } 
    }
    

    EDIT: const an der falschen stelle
    EDIT 2: verdeutlichung des anwendungsgebietes
    (kein Anspruch auf Richtigkeit)

    [ Dieser Beitrag wurde am 03.06.2003 um 12:11 Uhr von Mr. N editiert. ]



  • PS: Wer Placement-new verwendet, muss auch den Destruktor aufrufen.



  • Original erstellt von crass:
    Kann man Templates eigentlich nicht fast immer mit OOP ersetzen? Ich kenn mich nicht wirklich mit Templates aus (nur das Grundlegende) , aber zum Beispiel bei Container-Klassen wie Vector kann man ja anstatt das ganze zu templatisieren, auch einfach ein Objekt einer Wurzelklasse als Elementtyp verwenden,

    Kann man.

    Aber der Haken ist der, daß dadurch eine gemeinsame Basisklasse (a la "Object") geschaffen wird, die Klassenhierarchien miteinander verbindet, obwohl diese eigentlich keinen Zusammenhang haben.

    Bei Templates wird zwischen den verschiedenen Klassen aber streng unterschieden, sie sind nämlich _nicht_ im OO Sinne verwandt.

    Stichwort wäre also eher "Vermeidung von Modellverschmutzung".



  • Das würde ich niemals bezweifeln. Allerdings versuche ich *jeden* Tag mir ein winzig kleines bischen mehr Wissen anzueignen. Dabei stolpere ich dann häufig über sehr interessante Ideen die hier dann lustigerweise einfach als "Modewörter" abgetan werden ohne das sich derjenige die Mühe macht sich wenigstens mal zu informieren.

    Ich bin wirklich lieber jemand der keine Ahnung hat, das weiß und versucht dies Stück für Stück zu ändern, als jemand der meint er hätte schon alles gesehen und alles was er nicht kennt als schwachsinn abtut.

    😃 hehe, sehr gut ausgedrueckt!

    Also ich wuerd liebend gern dein "Unwissen" ueber C++ haben Hume.

    mfg
    v R



  • @marc++us
    also ich find das eigentlich keine Modellverschmutzung. Macht doch Sinn alle Klassen von einer gemeinsamen Wurzel abzuleiten.. der Vererbungstest mit "is a" klappt doch auch wunderbar auf eine Klasse "Object" ... Auto ist ein Objekt, Window ist ein Objekt, Vogel ist ein Objekt... passt doch!

    edit: ach so, ich glaub ich hatte dich falsch verstanden, du meinst man kann in einen Vector dann Objekte von allen möglichen Klassen reintun, die überhaupt nix miteinander zu tun haben.. das liegt natürlich dann beim Programmierer das zu vermeiden und is natürlich nicht so typsicher wie mit Templates.

    [ Dieser Beitrag wurde am 03.06.2003 um 13:23 Uhr von crass editiert. ]

    [ Dieser Beitrag wurde am 03.06.2003 um 13:27 Uhr von crass editiert. ]



  • Also, das mit der Typsicherheit hast Du schon richtig interpretiert.

    Aber auch der andere Fall ist nicht so ohne... da C++ Mehrfachvererbung erlaubt, ist es nicht unproblematisch alle Objekte von "object" abzuleiten.

    Und lustig ist das aus OO-Sicht auch, weil man überall bei Büchern zur OOA lesen kann, daß man eben _keine_ Selbstzweckvererbungen einführen soll, nur um Code zu sparen oder um Gemeinsamkeiten herauszustellen. Im Klartext: Vererbungen sollen dort auftreten, wo sie auch natürlicher Teil des Modells sind und keine zusätzlichen Abstraktionsebenen einführen. Also: Auto und Vogel haben keine gemeinsame Basisklasse, weil sie Objekte sind. Hier ist die Abstraktion zu weit getrieben. Sagt die OO-Literatur. Um aus diesem Dilemma herauszukommen, muß man die gemeinsame object-Oberklasse zu einem "Implementierungsdetail der Zielsprache" erklären... bißchen fragwürdig in meinen Augen. Ähnlich lösen das auch die UML-Tools, man zeichnet alle Abhängigkeiten und Vererbungen der Objekte ein, nur die Vererbung von object wird nicht gezeichnet, "weil die ja sowieso da ist". Würde man sie einzeichnen, wäre das Modell immer global zusammenhängen und es gäbe keine Objektfamilien und Inseln, wie es ja eigentlich Ziel der Modellierung war diese zu gewinnen.

    Templates lösen diese Sache in C++ eindeutig auf - ich kann in verschiedenen Themeninseln meines Modells auf die gleiche Template-Klasse zurückgreifen, ohne daß ich die Klassen der Themeninseln miteinander in Bezug setze. Das hat schon viele Vorteile.

    @<-> Hinweis zu Templates und Spielen

    In http://www.c-plusplus.net/titelanzeige.php?ISBN=3826609239 haben die Autoren den Themen "Spiele und STL" sowie "C++, Templates und Programmgeschwindigkeit" eigene Abschnitte gewidmet.



  • Marcus: Du vermischst die Ebenen. Du kannst in der OOA jedes Modell der Welt aufstellen, ohne die Programmiersprache zu berücksichtigen. Wie du das ganze dann implementierst, dh ob du Rücksicht auf eine evtl. vorhandene absolute Oberklasse nehmen mußt oder nicht, ist Gegenstand der OOP, und berührt dein OOA-Modell in keinster Weise.



  • Wer unterscheidet denn tatsächlich zwischen OOA-Vererbung und OOP-Vererbung? Das wird häufig als eine einzige Sache betrachtet.

    Die Ebenen treten nicht getrennt auf, sondern vermischt. Vor allem weil die Denkrichtung aus der Seite der Praktiker kommt... der OOPler denkt in Modellkategorien. Die Implementationssprache prägt das Bild des höheren Modells (auch wenn das natürlich nicht so sein sollte). Betrachtest Du nachher OOA-Modelle, so sieht man dann dann deutlich die Auswirkungen der OOP-Sprachen im Modell. Das ist nicht rückwirkungsfrei.



  • Original erstellt von Marc++us:
    Wer unterscheidet denn tatsächlich zwischen OOA-Vererbung und OOP-Vererbung? Das wird häufig als eine einzige Sache betrachtet.

    Anscheinend jeder Java-, Eiffel- oder Smalltalk-Programmierer. Denn die haben alle überhaupt kein Problem damit, dass alle Klassen von Object, ANY oder weiß-nicht abgeleitet sind, während diese Klassen in ihrer Analyse überhaupt nicht vorkommen.



  • Daß die genannte Zielgruppe wohl durchaus Verständnisprobleme damit hat sieht man an "Wofür Templates" und "ein Auto ist ein Objekt, ein Vogel ist ein Objekt".



  • Original erstellt von Marc++us:
    Daß die genannte Zielgruppe wohl durchaus Verständnisprobleme damit hat sieht man an "Wofür Templates"

    Smalltalk hat dynamische Typen und braucht sowas nicht, Eiffel hat Templates, Java wird sie haben.

    und "ein Auto ist ein Objekt, ein Vogel ist ein Objekt".

    Dass die genannten Gruppen kein Problem mit einer gemeinsamen Oberklasse haben, wird dadurch widerlegt, dass sie gemeinsame Oberklassen benutzen? Wow, tolle Argumentation.



  • und "ein Auto ist ein Objekt, ein Vogel ist ein Objekt".
    Dass die genannten Gruppen kein Problem mit einer gemeinsamen Oberklasse haben, wird dadurch widerlegt, dass sie gemeinsame Oberklassen benutzen? Wow, tolle Argumentation.

    Nein. Es geht nicht ums Benutzen, was lediglch pragmatisch ist, sondern darum, dass es hier so gerechtfertigt wird.

    Und lustig ist das aus OO-Sicht auch, weil man überall bei Büchern zur OOA lesen kann, daß man eben _keine_ Selbstzweckvererbungen einführen soll, nur um Code zu sparen oder um Gemeinsamkeiten herauszustellen.

    Nur ist es dann schwer irgendeinen Sinn in privater Vererbung, wie sie in C++ möglich ist, zu finden.

    Meine Erfahrung ist nur, dass Template-Wissen noch nicht so verbreitet ist. Ein gutes Beispiel ist z.B. der wirklich schlechte c't-Artikel "Generische Programmierung für bessere Wiederverwendbarkeit" von Dr. Markus Mohnen.

    Der Artikel war wirklich nicht grade toll. Aber in der nächsten c't hagelte es ja auch Leserbrife. Allerdings fand ich die Java-Erweiterungen an sich interesant, von denen icch ohne diesen Artikel nichts gewust hätte.



  • Kann man Templates eigentlich nicht fast immer mit OOP ersetzen?

    Sicher. Nur ist das Ergebnis nicht immer gleich zufriedenstellend. Mal ein ganz simples Beispiel. Das Interpreter-Pattern ist ein herrliches Design und fein OOP. Dummerweise im Alltag kaum zu gebrauchen. Ergänzt man es um die Möglichkeiten von Templates bleibt das Design fein wie eh und je und gleichzeitig wird es auch real anwendbar (siehe z.B. [url=http://research.microsoft.com/projects/greta/]GRETA-Regular Expression Lib[/ul])

    aber zum Beispiel bei Container-Klassen wie Vector kann man ja anstatt das ganze zu templatisieren, auch einfach ein Objekt einer Wurzelklasse als Elementtyp verwenden

    Wenn dann eine Referenz oder ein Zeiger -> C++ hat value-Semantik. Da macht ein Container mit Basisklassenobjekten nicht das was man von Java kennt.

    Ich verliere auf jeden Fall die statische Typprüfung, also kann ich genausogut auf void-Pointer umsteigen. Ich brauche also nicht mal OOP und eine gemeinsame Basisklasse.

    Naja, was ich mal von den Template-Freaks gern wissen würd, was (konkret) kann man wirklich nur mit Templates machen, was nicht durch OOP ersetzbar wäre (wenn die Sprache reinobjektorientiert ist und keinerlei primitive Datentypen hat) ?

    Nix. Templates machen C++ nicht mächtiger. Nur ausdrucksstärker.
    Das selbe gilt allerdings auch für OOP. Alles was man unter Verwendung von OOP berechnen kann, kann man auch ohne OOP berechnen. Zwei Zähler oder eine Turingmaschine sind alles was man braucht.
    Die Frage ist meiner Meinung nach völlig falsch gestellt.

    ach so, ich glaub ich hatte dich falsch verstanden, du meinst man kann in einen Vector dann Objekte von allen möglichen Klassen reintun, die überhaupt nix miteinander zu tun haben.. das liegt natürlich dann beim Programmierer das zu vermeiden und is natürlich nicht so typsicher wie mit Templates.

    Genau. Da hat man dann das "Warship in the pencil cup"-Phänomen 🙂

    Java wird sie haben

    Nachdem was ich bisher gelesen habe, aber doch nur in einer *sehr* beschränkten Art und Weise. Gut Container-T geht dann auch in Java und das ist ja auf jeden Fall schon mal ein großer Fortschritt.

    Nur ist es dann schwer irgendeinen Sinn in privater Vererbung, wie sie in C++ möglich ist, zu finden.

    Ich glaube Marcus sprach von öffentlicher Vererbung. Denn nur die gibt es soweit ich weiß in der OOA.
    Private Vererbung ist doch für Implementationsvererbung (is-implemented-in-terms-of).

    Der Artikel war wirklich nicht grade toll. Aber in der nächsten c't hagelte es ja auch Leserbrife

    Die imo kaum besser waren.

    Allerdings fand ich die Java-Erweiterungen an sich interesant, von denen icch ohne diesen Artikel nichts gewust hätte.

    Auf jeden Fall. Ich meinte auch nur den C++-Teil.



  • Original erstellt von HumeSikkins:
    **Wenn dann eine Referenz oder ein Zeiger -> C++ hat value-Semantik. Da macht ein Container mit Basisklassenobjekten nicht das was man von Java kennt.

    Ich verliere auf jeden Fall die statische Typprüfung, also kann ich genausogut auf void-Pointer umsteigen. Ich brauche also nicht mal OOP und eine gemeinsame Basisklasse.
    **

    Du verlierst die Laufzeittypprüfung. Wenn du dasselbe Verhalten wie in Java willst, mußt du eine Object-Klasse und dynamic_cast verwenden.



  • ich hab sicher nicht soviel Erfahrung und Wissen wie manche anderen hier über OO, aber ich hab einiges an praktischer Erfahrung und sehe zumindest daß es überaus praktisch ist eine Basisklasse wie Objekt zu haben. Nur so kann man zB bei jedem Objekt garantieren, daß es Methoden hat, die jedes Objekt haben sollte(bei einer praktischen Sprache die auf die Bedürfnisse der Programmierer zugeschnitten ist zumindest), zB toString(). Seh da nix falsches dran. Liegt vielleicht nur an meiner Verständnislosigkeit , aber solang meine Programme so laufen wie ich will(und das hat bis jetzt noch fast jedes), bin ich gern verständnislos:)



  • Original erstellt von Marc++us:
    Daß die genannte Zielgruppe wohl durchaus Verständnisprobleme damit hat sieht man an "Wofür Templates" und "ein Auto ist ein Objekt, ein Vogel ist ein Objekt".

    Jo! Javaprogrammierer sind alle Idioten, da sie nicht die Sichtweise eines C++-Programmierers haben. 🙄



  • [@Gregor: Während Du Dich vielleicht gerne als Java-Programmierer bezeichnest, bin ich kein C++-Programmierer. Nur so am Rande erwähnt.]

    Woher Du den Bogen zu Java spannst, ist mir nicht klar, weil es mir um die Problematik geht, daß allzu leicht Dinge aus den OO-Programmiersprachen in die Modelle übernommen werden. Ich führe die Antwort aus, weil ich Bashar noch eine Antwort schuldig bin. Falls Du hier weitere Argumente findest um den Thread in einen C++<->Java-Flame auszubauen, so sei Dir dies gegönnet.

    OOA und OOP sind laut Theorie getrennte Welten, wo die gleichen Begriffe (fatalerweise) für ähnliche, aber nicht identische Dinge benutzt werden. Katalogisiert man das in den Rahmen von Büchern, Vorlesungen oder Seminaren, so lassen sich die beiden Welten getrennt nebeneinander stellen.

    Leider ist das aber nicht ganz lebenswirklich.

    OOA ist trotz allem nach wie vor ein relativ filigranes und zerbrechliches Gebilde, das sich einer gewissen Gestaltungsfreiheit und festen Definition entzieht. Alleine die lange Zeit relativ große Notationsfreiheit hat dazu geführt, daß viele Dinge recht vage sind. UML tut hier etwas für mehr Regeln und Festigkeit, aber so richtig in den Köpfen ist das noch nicht.

    Ein Programm in einer OO-Sprache (und da will ich gar nicht diskutieren, wie stark C++, Java und C# jetzt "echte" OOP sind) ist dagegen was richtig Handfestes, sozusagen lecken, schmecken, fühlen. OOP prägt den Eindruck, den jemand aus der Objektorientierung mitnimmt, nicht die OOA. Bei der Analyse von Modellen arbeiten die meisten Leute eben in "Entwurfskategorien", da wird noch über das Modell nachgedacht und schon kommt "da machen wir ein Singleton draus" und "Publisher-Subscriber brauchen wir dafür". Ich denke, damit kann man in Grenzen leben und wird es in der Realität auch können.

    Als Lehrender und Lernender ist es dennoch von Zeit zu Zeit wichtig zu erkennen, daß dieses Denken in Implementierungsdetails natürlich übergeordnete Gedanken auch mal verstellt. Und da gefällt mir aus Sicht der Didaktik eben überhaupt nicht, wenn der Gedanke "jede Klasse erbt von einer Basisklasse" so drängend in den Vordergrund gerückt wird. Man sieht das manchmal [wo sich Leute die Mühe machen ihre Modelle grafisch aufzubereiten] in den Modellen der Programme, die haben so eine sternförmige Ableitungshierarchie, wo sich alles um eine "Sonne-Mond-Sterne-Klasse" dreht. Die tatsächlichen Themen-Cluster werden durch ein zwanghaftes "Ableiten von einer Basisklasse" überlagert. Man hat oftmals das Gefühl, daß ein Modell nicht OO ist, wenn nicht mindestes eine Ableitung drin vorkommt.

    Conclusio:

    1. Ich halte in OO-Sprachen die Ableitung von einer einzigen Basisklasse für unschön, weil hier Zusammenhänge künstlich konstruiert werden und zu falschen Lerneffekten führen können und nach meiner Erfahrung auch führen.
      [bösartiger Einwurf zu 1) Ich weiß, daß Supermänner keine falsche Lerneffekte haben und das trotzdem beherrschen. Dennoch gibt es viele Leute, die keine Supermänner sind. Man könnte sogar sagen, daß man mehr normale Leute findet, als Supermänner.]
    2. Templates helfen bei geschicktem Einsatz die Anzahl der Ableitungen zu reduzieren, weil man gemeinsame Eigenschaften nicht über eine Ableitung, sondern eine Template-Instanziierung realisieren kann.


  • Original erstellt von Marc++us:
    **@Gregor: Während Du Dich vielleicht gerne als Java-Programmierer bezeichnest, bin ich kein C++-Programmierer. Nur so am Rande erwähnt.]

    Woher Du den Bogen zu Java spannst, ist mir nicht klar,**

    1. Wie ich den Bogen zu Java spanne? Ganz einfach. Bashar hatte in seinem Beitrag explizit "Java-, Eiffel- oder Smalltalk-Programmierer" genannt. Sind das nicht die Leute, die du in deinem Beitrag als "Zielgruppe" bezeichnest? ...oder habe ich da was falsch verstanden.

    2. Eigentlich würde ich mich auch nicht als Javapgrammierer bezeichnen. Ich programmiere ja eigentlich fast garnicht. Nur hin und wieder mal ein kleines bischen.

    3. OK, der Bogen zum C++-Programmierer scheint falsch zu sein. Ich korrigiere mich hiermit, falls ich dich nicht komplett falsch verstanden habe:

    Java-, Eiffel- und Smalltalk-Programmierer Programmierer sind alle Idioten, weil sie nicht die Sichtweise von Marc++us haben! 🙂



  • @Gregor: Während Du Dich vielleicht gerne als Java-Programmierer bezeichnest, bin ich kein C++-Programmierer. Nur so am Rande erwähnt.]

    @marc++us
    deswegen kämst du ja auch nicht auf die idee den namen "deiner sprache" in deinen nickname zu integrieren, was 😉


Anmelden zum Antworten