binder: STL falsch verstanden oder Implementierung broken?



  • Hallo,

    ich arbeite erst seit kurzem verstärkt mit der STL und erweiterter Nutzung von Templates im Allgemeinen. Jetzt habe ich eine Methode, die einen String empfängt und diesen an mehrere Objekte in einer Liste weiterverteilen möchte (zur Verdeutlichung: Ein "job" hat mehrere "units". Ein "job" hat ein Basisverzeichnis, jede "unit" hat dort ein Unterverzeichnis):

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <functional>
    #include <vector>
    #include <algorithm>
    
    class unit {
    private:
      int index;
      std::string path;
    public:
      void set_path(const std::string& path_);
    };
    
    void unit::set_path(const std::string& path_)
    {
      std::stringstream str;
      str << path_ << "/" << index;
      path = str.str();
    }
    
    class job {
    private:
      std::string path;
    public:
      std::vector<unit*> units;
      void set_path(const std::string& path);
    };
    
    void job::set_path(const std::string& path_)
    {
      path = path_;
      std::for_each(units.begin(), units.end(), std::bind2nd( std::mem_fun( &unit::set_path ), path_));
    }
    
    int main(void)
    {
      job myJob;
      myJob.units.push_back(new unit());
      myJob.set_path("/tmp/irgendwo");
    }
    

    In der for_each Zeile bekomme ich den Fehler

    /usr/include/c++/3.3/bits/stl_function.h:393: error: forming reference to reference type `const std::string&'

    Wenn ich den Parametertyp von set_path von const std::string& auf std::string ändere funktionierts. Sehe ich den Wald vor lauter Bäumen nicht, ist meine STL broken oder beherrschen die STL-Binder wirklich nur Wertübergabe?



  • Hmm, ist das nicht die Baustelle von boost:: (c)ref? Wenn ja, dann probiers damit, ansonsten übergib halt einen Zeiger.
    Ist im übrigen kein schönes Design. (Hoffentlich nur ein Beispiel ...)



  • LordJaxom schrieb:

    /usr/include/c++/3.3/bits/stl_function.h:393: error: forming reference to reference type `const std::string&'

    Wenn ich den Parametertyp von set_path von const std::string& auf std::string ändere funktionierts.

    Das Problem "reference to reference" ist bekannt. Ich find' jetzt gerade keinen Link, wo es erklärt wird. Die Änderung zu 'per value' statt 'per reference' ist der einzige mir bekannte Workaround.
    Das ist einer der Gründe warum bei den Bindern lieber boost::bind statt std::bind* nehmen soll.
    In diesem Fall:

    std::for_each(units.begin(), units.end(), boost::bind( &unit::set_path, _1, path_ ) );
    

    Gruß
    Werner



  • Vielen Dank, hab ich mir schon fast gedacht...

    Das Beispiel ist das berühmte Minimalbeispiel um das Problem zu demonstrieren, und kein Produktivcode, genau wie Ihr es immer predigt (und auch ich es natürlich am liebsten habe)

    Die Benutzung von boost kommt erstmal nicht in Betracht (ich kenne die Zielgruppe und deren Abneigung gegen neue Abhängigkeiten sehr genau 😉 ), vielleicht kopier ich mir aber doch mal ein paar Header-Only Sachen (glaube bind gehört dazu) zusammen und liefer sie direkt mit meinem Code aus.



  • boost::binder gehört zum TR1, also ist vom ISO-C++ Kommittee abgesegnet. Ist also keine externe Abhängigkeit. Du kannst auch den TR1-Wrapper von Boost benutzen, dann ist auch alles im richtigen Namespace std::tr1.

    Hach, ich glaub ich muß wirklich mal einen TR1-Artikel für das C++ Magazin schreiben. Kann ja nicht sein, das die C++ Scene immer noch keinen TR1 kennt?



  • Nen Artikel dazu was wir demnächst im Standard erwarten dürfen wäre in der Tat sehr nett 😉

    EDIT:
    Mit boost::bind klappt mein Code übrigens sehr gut, konnte mir sogar noch ein paar Hilfsfunktoren sparen, danke 😉


Log in to reply