Funktion als Template-Argument: wie zwischen 2 overloads unterschieden?



  • Hi!

    Ich moechte einem boost::thread eine Funktion zum Ausfuehren mitgeben. Allerdings gibts von der Funktion 2 Overloads, und der GCC (4.1) kann anscheinend nicht entscheiden welche der beiden ich meine:

    // das sind die funktionen:
    template<typename ParseReadsCallback> void parse_reads(const std::string& dir, ParseReadsCallback& callback);
    template<typename ParseReadsCallback> void parse_reads(const char* dir, ParseReadsCallback& callback);
    
    class ReadDetailsCallbacks
    {
        operator() (...)  // callback fuer parse_reads
    
        ReadInfoMapPtr get_reads(const std::string& foo)
        {
            string dir = ...
            thread t1(parse_mapping_short<ReadDetailsCallbacks>, dir, ref(*this));  // <<<--- Hier passiert der Fehler!
        }
    };
    

    Und das ist die Fehlermeldung:

    error: no matching function for call to 'boost::thread::thread(<unresolved overloaded function type>, std::string&, const boost::reference_wrapper<ReadDetailsCallbacks>)'
    include/boost/thread/detail/thread.hpp:199: note: candidates are: boost::thread::thread(boost::detail::thread_move_t<boost::thread>)
    include/boost/thread/detail/thread.hpp:147: note:                 boost::thread::thread()
    include/boost/thread/detail/thread.hpp:118: note:                 boost::thread::thread(boost::detail::thread_data_ptr)
    include/boost/thread/detail/thread.hpp:108: note:                 boost::thread::thread(boost::thread&)
    readdetails.cpp: In member function 'ReadInfoMapPtr ReadDetailsCallbacks::get_reads(const std::string&)':
    

    Wie kann ich dem GCC erklaeren, welche der 2 parse_reads()-overloads ich haben moechte?

    EDIT: code-beispiel ausgeweitet damit die Fehlermeldungen mehr Sinn machen.



  • Du musst die parameter mit bind "binden" damit eine aufrufbare funktion entsteht.
    Du brauchst ein boost::function<void()> das du übergibst.



  • evilissimo schrieb:

    Du musst die parameter mit bind "binden" damit eine aufrufbare funktion entsteht.
    Du brauchst ein boost::function<void()> das du übergibst.

    D.h. es gibt keinen Weg, wie man das mit "reinem C++" loest (d.h. ohne boost::function)?



  • Blue-Tiger schrieb:

    evilissimo schrieb:

    Du musst die parameter mit bind "binden" damit eine aufrufbare funktion entsteht.
    Du brauchst ein boost::function<void()> das du übergibst.

    D.h. es gibt keinen Weg, wie man das mit "reinem C++" loest (d.h. ohne boost::function)?

    natürlich gibt es den aber es ist umständlich ausserdem erwartet der thread constructor ein function object oder etwas das dorthin transformierbar ist. Das bedeutet deine Fehlermeldung.



  • Blue-Tiger schrieb:

    Ich moechte einem boost::thread eine Funktion zum Ausfuehren mitgeben. Allerdings gibts von der Funktion 2 Overloads, und der GCC (4.1) kann anscheinend nicht entscheiden welche der beiden ich meine:

    // das sind die funktionen:
    template<typename ParseReadsCallback>
    void parse_reads(const std::string& dir, ParseReadsCallback& callback);
    
    template<typename ParseReadsCallback>
    void parse_reads(const char* dir, ParseReadsCallback& callback);
    
    class ReadDetailsCallbacks
    {
        operator() (...)  // callback fuer parse_reads
    
        ReadInfoMapPtr get_reads(const std::string& foo)
        {
            string dir = ...
            thread t1(parse_mapping_short<ReadDetailsCallbacks>,
                dir, ref(*this));
        }
    };
    

    Du meintest sicherlich parse_reads und nicht parse_mapping_short, ja?

    Ok, das ist halb so schlimm. Der Grund, warum's nicht geht ist, wie Du schon erkannt hast, dass das Funktionstemplate überladen ist. Daher bezeichnet parse_reads<ReadDetailsCallbacks> eine Menge von 2 Funktionsspezialisierungen. Eine solche Menge kann aber nicht für die "Template-Argument-Deduction" verwendet werden. "Template-Argument-Deduction" (TAD) muss hier aber stattfinden, weil Du einem Konstruktortemplate (in diesem Fall den vom boost::thread) die Template-Parameter nicht explizit mitgeben kannst. Lösen kann man das, indem Du Dir zB eine Zeigervariable für die Funktion anlegst:

    void (*funptr)(const std::string&, ReadDetailsCallback) =
       parse_reads<ReadDetailsCallbacks>;  // 1
    thread t1(funptr, dir, ref(*this));    // 2
    

    1. hier kann der Compiler aus der Menge der Funktionen die richtige rausfischen, die zum Funktionszeiger-Typen passt.
    2. TAD funktioniert, da der Typ von funptr bekannt ist.

    Gruß,
    SP



  • thx euch beiden! 🙂

    Die Loesung von Sebastian funkioniert und erspart mir das Lesen der boost::bind doku 😉


Anmelden zum Antworten