Ergebnis von boost::bind explizit nach boost::function casten - Wieso ist das nötig?



  • Und schon wieder ein Problem:

    class Server {
    public:
        register(boost::function<void(const std::string&)> f);
    };
    
    class Foo {
    public:
        Foo(Server& serv) { serv.register(boost::bind(&Foo::bar, this, _1));}
        void bar(const std::string&) {std::cout << bar << std::endl;}
    };
    

    Kompiliert nicht mit der Mitteilung das

    boost::_bi::bind_t<void, boost::_mfi::mf1<void, Foo, const std::string&>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >
    

    nicht in

    boost::function<void(const std::string&)>
    

    konvertiert werden kann.

    Wenn ich es explizit nach boost::function<void(const std::string&)> caste, gehts durch den Kompiler und funktioniert hinterher auch.

    Warum?
    Fällt aus boost::bind keine boost::function raus?

    Philipp



  • Du nennst deine Funktion nicht wirklich register? Sonst geht das eigentlich schon.



  • PhilippM schrieb:

    Und schon wieder ein Problem:

    class Server {
    public:
        register(boost::function<void(const std::string&)> f);
    };
    
    class Foo {
    public:
        Foo(Server& serv) { serv.register(boost::bind(&Foo::bar, this, _1));}
        void bar(const std::string&) {std::cout << bar << std::endl;}
    };
    

    Kompiliert nicht mit der Mitteilung das

    boost::_bi::bind_t<void, boost::_mfi::mf1<void, Foo, const std::string&>, boost::_bi::list2<boost::_bi::value<Foo*>, boost::arg<1> > >
    

    Was du da gepsotet hast compiliert sicher nicht mit der Fehlermeldung (dafür sind zu viele Fehler drin). Wenn du Hilfe willst, solltest du den tatsächlichen Code oder ein minimales Beispiel, das den Fehler reproduziert, posten. Ohne die anderen Fehler geht's jedenfalls.



  • Natürlich ist das stark zusammengekürzt. Und die Funktion heißt natürlich auch nicht "register"-was ja ein Schlüsselwort wäre.

    Ich bemühe mich halt immer, möglichst nur die "verdächtigen" Codestellen zu posten, da ich weiß, dass keiner Lust hat, 500 Zeilen-Postings zu lesen wo einer einfach mal das ganze Programm postet mit der Bitte, doch den Fehler rauszumachen.

    Hier habe ich aber wohl zuviel gekürzt.

    Das sollte vollständiger, aber wahrscheinlich nicht einfacher zu verstehen sein:

    class Receiver
    {
    public:
        template <typename T>
        void requestData(can_Id_t can_id, boost::function<void (const T&)> f, T* t);
    ...
    };
    
    class FSAccessSCSImpl : public FSAccess, public Receiver
    {
        Q_OBJECT
    public:
        FSAccessSCSImpl() {
            requestData(UTC_TIME::Id(),
                        boost::function<void(const char4&)>(boost::bind(&FSAccessSCSImpl::resetTimer, this, _1)), 
                        &m_time);
    }
    
    protected:
    
        void resetTimer(const char4&);
    
    private:
        char4 m_time;
    };
    

    Das funktioniert so.
    Aber man beachte den Cast

    boost::function<void(const char4&)>(boost::bind(&FSAccessSCSImpl::resetTimer, this, _1))
    

    Ohne den cast tritt oben genannter Fehler auf.

    Kann es sein, dass boost::_bi::bint_t<... nach boost::function<... konvertierbar ist, aber die Konversion nicht benutzt wird, um das richtige Funktionstemplate auszuwählen?

    Philipp



  • Muss denn der Parameter unbedingt gleich ein boost::function-Objekt sein? Gib doch die Funktion direkt per template-Parameter mit (geht auch mit boost::bind):

    #include <boost/bind.hpp>
    #include <boost/function.hpp>
    #include <string>
    #include <iostream>
    
    struct Fun {
      template <typename Fun, typename T>
      void run(Fun fun, T const& t) {
        fun(t);
      }
    };
    
    struct Test {
      void run() {
        Fun f;
        f.run(boost::bind(&Test::test, this, _1), std::string("Hallo"));
      }
      void test(const std::string& s) {
        std::cout << s << std::endl;
      }
    };
    
    int main() {
      Test t;
      t.run();
    }
    


  • PhilippM schrieb:

    Fällt aus boost::bind keine boost::function raus?

    Nein. Aber es sollte bei "kompatiblen Signaturen" in ein entsprechendes boost::function<>-Objekt konvertierbar sein.

    Es sollte auch möglich sein, ein reduziertes, vollständiges Beispiel zu präsentieren. Ja, dazu musst Du 'n bissel Hand anlegen.



  • krümelkacker schrieb:

    PhilippM schrieb:

    Fällt aus boost::bind keine boost::function raus?

    Nein. Aber es sollte bei "kompatiblen Signaturen" in ein entsprechendes boost::function<>-Objekt konvertierbar sein.

    Ahh, das erklärt einiges. Es bestätigt auch meine Vermutung: Wenn ich die Funktion testweise ohne Template hinschreibe, so dass sie nur boost::function<void(const char4&)> erwartet, klappts plötzlich auch ohne cast. Offenbar versucht der Kompiler nicht das Argument implizit in etwas zu konvertieren, was aufs Teplate passt.

    Ist auch irgendwie logisch, denn das template muss ja erstmal instantiiert werden. Denn dann müsste der kompiler ja erstmal alle implizieten konvertierungen eines typs erzeugen und sich dann aus den Fingern saugen, zu welcher er das template instantiieren soll.

    Philipp



  • PhilippM schrieb:

    Ist auch irgendwie logisch, denn das template muss ja erstmal instantiiert werden. Denn dann müsste der kompiler ja erstmal alle implizieten konvertierungen eines typs erzeugen und sich dann aus den Fingern saugen, zu welcher er das template instantiieren soll.

    Ich glaube du meinst schon das richtige, aber ich würde es anders ausdrücken: die Type-Deduction haut nicht hin, weil dabei - vermutlich - keine userdefinierten Konvertierungen berücksichtigt werden (müsste das nachschlagen, klingt aber logisch).


Anmelden zum Antworten