std::function<> und Rvalue-Referenzen



  • Hallo!
    Mit Google konnte ich leider nicht viel außer einen VS-Bug finden, der sich auf das Problem beziehen könnte, es geht um Rvalue-Referenzen in std::function<>-Objeken:

    #include <function>
    #include <iostream>
    
    void test(int&& i, char c) {
    	std::cout << i;
    }
    
    int main() {
    	std::function<void (int&&, char)> f(test);
    	auto function = std::bind(f, std::placeholders::_1, 'A');
    	function(5);
    }
    

    So rein theoretisch/semantisch müsste das doch eigentlich funktionieren, tut's aber nicht. Irgendwo in den Tiefen der Fehlermeldungen von std::function finde ich:

    error C2664: 'void std::tr1::_Function_impl2<_Ret,_Arg0,_Arg1>::operator ()(_Arg0,_Arg1) const': Konvertierung des Parameters 1 von 'int' in 'int &&' nicht möglich
    Ein lvalue kann nicht an einen rvalue-Verweis gebunden werden.
    

    Was ist falsch?



  • Scheint so, als ob die Mitarbeiter Microsofts bei der Implementierung von std::function ein paar mal std::forward vergessen haben. Die "rvalue-ness" der 5 müsste eigentlich durchgehend erhalten bleiben. Müsste in diesem konkreten Fall etwa so aussehen (pseudo code):

    class function<void(int&&,char)>
    {
      ....
      void operator()(int&& a, char b) const
      {
        return abc_ptr->invoke(std::forward<int&&>(a), std::forward<char>(b));
      }
      ....
      unspezifizierter-typ *abc_ptr;
    };
    

    wobei über abc_ptr das gewrappte Funktionsobjekt erreichbar ist. So etwas ähnliches müsste dann auch in der invoke-Funktion gemacht werden.



  • Das heißt, ich kann function nicht benutzen. Ich brauche es aber (wegen bind). Und Rvalue-Referenzen brauche ich auch, da der Typ definitiv nicht kopierbar sein soll. Was kann ich jetzt machen?



  • Das ist der Nachteil wenn man experimentelle Features nutzt. Auf ein Update der Dinkumware-Bibliothek warten wäre wohl die beste Möglichkeit ...



  • Und wenn du ja schon C++0x nutzt, könntest du ja auch gerade decltype nutzen:

    void test(int&& i, char c) { 
        std::cout << i; 
    } 
    
    int main() { 
        std::function<decltype(test)> f(test); 
        auto function = std::bind(f, std::placeholders::_1, 'A'); 
        function(5); 
    }
    


  • Jodocus schrieb:

    Und Rvalue-Referenzen brauche ich auch, da der Typ definitiv nicht kopierbar sein soll. Was kann ich jetzt machen?

    Wie hättest du es in C++98 gelöst?

    Referenzen und swap() sind eine Möglichkeit, Smart-Pointer eine andere. Zeig mal etwas konkreten Code.



  • > Wie hättest du es in C++98 gelöst?

    Die Frage habe ich mir auch gestellt und kam auf Smart-Pointer. Aber ideal finde ich es nicht.

    Meine dreckige Idee: ich mache es wie std::auto_ptr. Der Kopierkonstruktor der Resourcenklasse ist private - logisch. Was nun, wenn ich std::function<> in der Klasse als Friend deklariere? Geht das? Darf man das? Denn dann könnte ich den Kopierkonstruktor wie bei auto_ptr move-Eigenschaften geben und auf Rvalue-Referenzen verzichten.

    @ EOutofRessources: Was bringt mir decltype() da? Das ist doch unterm Strich der selbe Typ - die selbe Fehlermeldung.


Anmelden zum Antworten