std::list::push_back an Bedingung knüpfen



  • Hallo Forum,

    ich möchte Instanzen meiner Klasse MyClass in einer Liste darstellen und verwende dazu das STL-Template std::list<MyClass> . Lässt sich nun die Memberfunktion push_back() irgendwie überschreiben und durch eigenen Code ersetzen? Zum Beispiel soll vor dem Einfügen überprüft werden, ob das für diesen Listentyp überhaupt zulässig ist. Ich habe mir auch gedacht, einen Wrapper zu schreiben, aber ich finde es Unfug, jede Memberfunktion in meinem Wrapper, an std::list weiterzuleiten. Gibt es denn keine elegantere Lösung?

    Grüße,

    daersc


  • Mod

    daersc schrieb:

    Zum Beispiel soll vor dem Einfügen überprüft werden, ob das für diesen Listentyp überhaupt zulässig ist.

    Was meinst du damit?

    Ich habe mir auch gedacht, einen Wrapper zu schreiben, aber ich finde es Unfug, jede Memberfunktion in meinem Wrapper, an std::list weiterzuleiten. Gibt es denn keine elegantere Lösung?

    Du kannst von den STL-Containern erben.


  • Administrator

    SeppJ schrieb:

    Du kannst von den STL-Containern erben.

    Kann man, würde ich aber nicht empfehlen! Denn die Destruktoren der Container aus der Standardbibliothek müssen nicht virtuell sein. Zudem ist es fraglich, ob hier eine Is-A Beziehung wirklich zutrifft.

    Ich denke, dass ein Wrapper hier definitiv der beste Ansatz ist.

    Grüssli



  • SeppJ schrieb:

    daersc schrieb:

    Zum Beispiel soll vor dem Einfügen überprüft werden, ob das für diesen Listentyp überhaupt zulässig ist.

    Was meinst du damit?

    Ach Kacke, was hab ich da für nen Müll geschrieben... Ich wollte überprüfen, ob irgendetwas dagegen spricht, das Element auch tatsächlich zur Liste hinzuzufügen. MyClass beinhaltet Zeiger auf zwei Objekte einer anderen Klasse. Es sollte pro Liste aber nur jeweils einmal auf das selbe Objekt verwiesen werden.

    Ich habe mir auch gedacht, einen Wrapper zu schreiben, aber ich finde es Unfug, jede Memberfunktion in meinem Wrapper, an std::list weiterzuleiten. Gibt es denn keine elegantere Lösung?

    Du kannst von den STL-Containern erben.

    Kann ich dann auch den Cast zu den STL-Containern verhindern? Sonst könnte ja jemand casten und dann doch mit seinem push_back() tun und lassen, was er will...


  • Mod

    daersc schrieb:

    Kann ich dann auch den Cast zu den STL-Containern verhindern? Sonst könnte ja jemand casten und dann doch mit seinem push_back() tun und lassen, was er will...

    Gegen böse Absicht kannst du dich ohnehin nicht wehren. Der Einsatz von Casts zeigt ja, dass sich der Programmierer (hoffentlich 🙂 ) bewusst ist, was er da tut.



  • daersc schrieb:

    Kann ich dann auch den Cast zu den STL-Containern verhindern? Sonst könnte ja jemand casten und dann doch mit seinem push_back() tun und lassen, was er will...

    Der Anlass, dies verhindern zu wollen, deutet stark darauf hin, dass Vererbung der falsche Ansatz ist. Nur aus Bequemlichkeit, um sich vor ein paar einzeiligen Weiterleitungsfunktionen zu drücken, sollte man nicht vererben! Wie schon von Dravere angedeutet, trifft die Is-A-Beziehung (und das Liskonvsche Substitutionsprinzip) hier nicht zu, was Aggregation als Gliederungsmechanismus nahelegt.

    SeppJ schrieb:

    Der Einsatz von Casts zeigt ja, dass sich der Programmierer (hoffentlich 🙂 ) bewusst ist, was er da tut.

    Eine Derived-to-Base-Konvertierung benötigt keinen Cast. Wie bei allen impliziten Konvertierungen besteht die Gefahr, dass sie unbewusst passiert. Wenn dann die Semantik nicht der erwarteten entspricht, bekommt man schnell sehr mühsame Probleme.

    Allerdings scheint mir eine freie Funktion die beste Idee zu sein.

    template <typename T>
    void specific_push_back(std::list<T>& list, const T& element)
    {
        ... // spezifische Aktionen
        list.push_back(element);
    }
    


  • Nexus schrieb:

    Allerdings scheint mir eine freie Funktion die beste Idee zu sein.

    template <typename T>
    void specific_push_back(std::list<T>& list, const T& element)
    {
        ... // spezifische Aktionen
        list.push_back(element);
    }
    

    Und dann kommt irgendein Dödel und verwendet std::list::push_back() ...
    Ich glaube der Wrapper ist doch die beste Alternative.

    Danke:-)



  • Ich habe halt angenommen, dass

    daersc schrieb:

    ich möchte Instanzen meiner Klasse MyClass in einer Liste darstellen und verwende dazu das STL-Template std::list<MyClass> .

    nicht überall über das Programm verstreut vorkommt, sondern vielleicht nur an einem oder wenigen Orten. Und dann wäre es den Aufwand nicht wert, alle Funktionen weiterzuleiten.

    Aber natürlich ist ein Wrapper die sicherste Möglichkeit. Ich würde bei der Gelegenheit aber gerade das Interface verkleinern. Brauchst du Dinge wie splice() , get_allocator() oder pop_front() ?


Log in to reply