std::sort nach verschiedenen Objekteigenschaften mit Standardprädikaten (ohne Extrafunktion!)



  • question123 schrieb:

    Jein. Die Vergleichsfunktionen existieren ja schon.

    Nein tun sie nicht. Was glaubst du was greater<Object> macht? oder dein vorgeschlagenes greater<Object::element> ? Da wird ein Klassentemplate instantiiert, damit erzeugt der Compiler den Code für einen Funktor, der den operator> aufruft. Bei allen anderen vorgeschlagenen Lösungen wird so ein Funktor auf mehr oder weniger komplizierte Art vom Compiler zusammengebastelt - im einfachsten Fall ohne irgendwelche template-Instantiierung auf die handcodierte Art. Im allereinfachsten Fall ist es natürlich deine einfache Funktion, ohne dass irgendein Funktor-Objekt konstruiert werden müsste.
    Be einfachen Funktoren hat der Compiler gute Chancen dass ein Großteil des generierten oder selbstgetippten Codes wegoptimiert wird und lediglich die Essenz des Vergleichs übrig bleibt - nämlich der operator>.



  • Hey, eine der Varianten kam ohne Funktor aus! 🙂



  • knivil schrieb:

    Und man sieht wieder, wie aus einer simplen Sache unglaublich viel Code entsteht. Ich finde die vorgeschlagenen Loesungen schlecht.

    Du sagst ohnehin immer, dass Du alles schlecht findest ohne dabei irgendwelche Lösungen beizutragen. Mach doch einen besseren Vorschlag, wenn es so schlecht ist.

    Mal ganz davon abgesehen widersprichst Du Dir a) selbst, und b) ist die Menge an generiertem Code doch sehr überschaubar.



  • pumuckl schrieb:

    Nein tun sie nicht. Was glaubst du was greater<Object> macht? oder dein vorgeschlagenes greater<Object::element> ?

    Ich meinte mit "sie existieren schon" ein bisschen was anderes, nämlich nicht, dass dafür nicht extra Code (durch den Compiler) erzeugt werden müsste (was klar ist), sondern dass ich als Programmierer gerne auf bestehende Konstruktionen zurückgreifen würde.

    Nexus (und Decimad) haben ja eine sehr schöne und allgemein verwendbare Möglichkeit aufgezeigt. (Danke dafür schon mal, 👍!) Was mich wundert: Da das Problem, Objekte (Klasseninstanzen) nach verschiedenen Eigenschaften sortieren zu wollen, so selten nicht ist, dass C++ (inkl. STL) da keine Bordmittel hat...



  • Da halt ich es wie die Mathematiker. Sie koennen auch Beweise ablehnen, ohne einen richtigen zu liefern. Desweiteren entspricht es nicht den Anforderungen des Threadstellers:

    (ohne Extrafunktion!)

    Da das aber nicht moeglich ist (es wurden Extrafunktionen/Functoren geschrieben), warum sollte ich eine weitere (Un)loesung liefern. Ausserdem ist die Generalisierung ueber Templates genauso wie fruehzeitige Optimierung ...



  • knivil schrieb:

    Ausserdem ist die Generalisierung ueber Templates genauso wie fruehzeitige Optimierung ...

    OMG, da würde man ja etwas lernen.

    Die Lösung ist gut. Nicht ideal - aber das liegt an der Aufgabenstellung.



  • Hey, ich fand die Aufgabenstellung gut! 😉



  • Nexus schrieb:

    question123, kommt das jetzt noch ein wenig näher? Ist es sogar schon gut genug? 🙂

    Bin verwirrt. Ich krieg's nicht zum Laufen:
    minimal5.cxx:75: error: no matching function for call toCompare(int (some::*)())'`
    😕



  • Nexus'-Lösung sieht vor, dass man getter-Funktions-Zeiger verwendet, anstatt Daten-Member-Zeiger. Adaptiere meine längere Lösung von der ersten Seite so, dass sie der Implementierung von Nexus gleichkommt. Oder füge bei Nexus die Daten-Member-Zeiger statt der Methoden-Zeiger ein.



  • Ja, aber ich verwende doch Funktionszeiger? Oder bin ich grad auf dem Holzweg??

    struct some {
        int _a;
        int _b;
        int a(void) { return _a; };
        int b(void) { return _b; };
        some(int a1, int b1) : _a(a1), _b(b1) {}
    };
    
    std::sort(l.begin(), l.end(), Compare( &some::a ));
    


  • Ahh, okay... du hast die const-qualifier an den Getter-Methoden vergessen.



  • Dachte ich auch mal 🙂 Aber

    ...
    const int a(void) { return _a; };
    ...
    

    bringt auch nur minimal5.cxx:70: error: no matching function for call toCompare(const int (some::*)())'`



  • int a(void) const { return _a; };
    

    So.



  • Im Prinzip ist dashier genau dasselbe wie die "Key Extractor" bei Boost.Multiindex.

    http://www.boost.org/doc/libs/1_38_0/libs/multi_index/doc/reference/key_extraction.html



  • Decimad schrieb:

    So.

    Danke. Scheint Zeit zu sein, nach Hause zu gehen 🙂



  • knivil schrieb:

    Da halt ich es wie die Mathematiker. Sie koennen auch Beweise ablehnen, ohne einen richtigen zu liefern.

    Kritik ist okay, sofern sie begründet ist. Aber Aussagen wie "ich finde das schlecht, zu viel Code" helfen niemandem. Du bist übrigens immer noch nicht auf meine Fragen im letzten Post eingegangen. Insofern kann ich Tachyon nur zustimmen...

    question123 schrieb:

    Bin verwirrt. Ich krieg's nicht zum Laufen

    Tut mir leid, ich hab die Funktionszeiger mal auf const -Versionen beschränkt, da diese für die meisten Fälle reichen sollten. Ausserdem scheint mir das sinnvoller als direkten Zugriff auf Member, da so die Zugriffsrechte der Klasse bewahrt werden können. Natürlich kannst du noch nach Belieben erweitern.



  • Wenn du die Funktionalität generisch implementieren willst ...

    Genau das stoert mich. Warum sollte man es generisch loesen wollen/sollen? Normalerweise sind Klassen recht unterschiedlich (wenn nicht, dann sollte man nochmal drueber nachdenken), und eine generische Loesung nur auf ein oder zwei Typen anwendbar. Ausserdem kommt dann sowas raus:

    Bin verwirrt. Ich krieg's nicht zum Laufen

    da er sich nicht nur um die Sortierfunktion kuemmern muss, sondern sich auch noch durch die Templates wuehlen muss. Im Endeffekt wird es wahrscheinlich einfach nur kopiert. Boost::Lambda ist ok. Aber ich finde, es ist ungeeignet fuer Anfaenger. Die eigentliche Aussage, fuer eigene Klassen braucht man eigene Vergleichsfunktionen, ist voellig untergegangen.



  • knivil schrieb:

    Genau das stoert mich. Warum sollte man es generisch loesen wollen/sollen? Normalerweise sind Klassen recht unterschiedlich (wenn nicht, dann sollte man nochmal drueber nachdenken), und eine generische Loesung nur auf ein oder zwei Typen anwendbar.

    Es ging ja darum, ein Objekt (in einem Container) wahlweise nach gewissen Eigenschaften der Klasse zu sortieren, ohne für jede Eigenschaft eine eigene Funktion zu schreiben. Das ist wohl auch mit generisch gemeint. Und wieso sollte sich das nicht auszahlen? Man kann damit jede Klasse, die Get-Memberfunktionen mit der vorgegebenen Schnittstelle anbietet, nach irgendeinem Wert sortieren.

    knivil schrieb:

    Ausserdem kommt dann sowas raus:

    Bin verwirrt. Ich krieg's nicht zum Laufen

    da er sich nicht nur um die Sortierfunktion kuemmern muss, sondern sich auch noch durch die Templates wuehlen muss. Im Endeffekt wird es wahrscheinlich einfach nur kopiert. Boost::Lambda ist ok. Aber ich finde, es ist ungeeignet fuer Anfaenger.

    Und jetzt? Wir können ihn ja dabei unterstützen. Er muss auch nicht alles hinter dem Code verstehen, um ihn anwenden zu können. Ich sags gerne nochmals: Wenn man meine Templates in einen separaten Header auslagert, braucht man nur die Compare() -Funktion richtig aufzurufen, und alles funktioniert. Wo liegt das Problem?

    Ich kann nicht ganz nachvollziehen, wie du hier krampfhaft versuchst, sämtliche Vorschläge in diesem Thread schlechtzureden, noch dazu, ohne selber etwas beizutragen. Der Threadersteller ist zufrieden, was willst du denn erreichen? Willst du ihn von einzelnen Funktionen für jedes Attribut überzeugen - dem Punkt, von dem er ursprünglich wegkommen wollte? 🙄

    knivil schrieb:

    Die eigentliche Aussage, fuer eigene Klassen braucht man eigene Vergleichsfunktionen, ist voellig untergegangen.

    Was hat denn das damit zu tun? Das war nur eine Frage während des Threadverlaufs, die aber inzwischen geklärt sein sollte. Mit meiner Lösung braucht man beispielsweise nicht mehr spezifische Vergleichsfunktionen (es ging ums Schreiben des Codes, nicht welcher Code schlussendlich durch die Template-Instanziierungen erzeugt wird).



  • Was hat denn das damit zu tun?

    Der Threadtitel lautet so ...

    Er muss auch nicht alles hinter dem Code verstehen, um ihn anwenden zu können.

    Da bin ich halt anderer Meinung.

    Der Threadersteller ist zufrieden,

    Ja, aber hat er was gelernt? Fraglich ...



  • knivil schrieb:

    Er muss auch nicht alles hinter dem Code verstehen, um ihn anwenden zu können.

    Da bin ich halt anderer Meinung.

    Da kann man jetzt wieder mit der üblichen Gegenfrage kommen: wie weit muss man das verstehen, was "hinter" dem verwendeten Code steckt? Die hier präsentierten Lösungen könnten (mit ein wenig Zusatzarbeit, z.B. Unterstützung von const-gettern und nonconst-gettern) durchaus in einer Bibliothek angeboten werden, die man so verwendet wie sie daher kommt und wo es reicht das Interface zu kennen und anwenden zu können.
    Deiner Aussage zufolge muss man aber alles hinter dem verwendeten Code verstehen, um ihn anwenden zu können. Weißt du wie die von deinem Compiler verwendete STL-Implementation intern funktioniert mit ihren vermutlich zigfach delegierten Implementationen von Iteratortemplates usw? Kennst du dich genug mit Assembler etc. aus um zu wissen wie die einzelnen Maschinenbefehle für diese Implementationen aussehen? Hast du Ahnung von Prozessoren und weißt wie dort die einzelnen Schritte auf die verschiedenen Register verteilt werden? Hast du das nötige Wissen von Mikroelektronik um zu wissen wie im Prozessor die einzelnen Schaltungen erfolgen? Wieviel Ahnung hast du von Halbleiterphysik, verstehst du was da innerhalb der einzelnen Schaltkreise auf dem Prozessor vor sich geht? In dem Zusammenhang fehlt dann auch noch Quantenphysik, weil bei heutigen Schaltzeiten und Schaltkreisabmessungen Tunneleffekte und andere Quantenmechanische Dinge eine Rolle spielen. Wenn man den Ansatz "du musst verstehn was dahinter steckt" wirklich ernst nimmt dann muss man vor dem ersten "Hello World" erstmal ein paar Jahre Grundlagenstudium absolvieren.

    knivil schrieb:

    und eine generische Loesung nur auf ein oder zwei Typen anwendbar.

    Noch so eine Aussage ohne jeden Beleg und Hintergrund. Schau mal im Netz was "generisch" heißt. Ganz bestimmt steht da dann nicht "etwas, was man nur ein oder zweimal anwenden kann". Mal ganz abgesehn davon dass die gezeigten Lösungen nur einen ganz normalen Getter für das benötigte Attribut erwarten, und den gibts in so ziemlich jeder Klasse die das entsprechende Attribut der Außenwelt zugänglich machen möchte.


Anmelden zum Antworten